Merge "Adds the keyguard indication area overlays" into qt-dev
diff --git a/Android.bp b/Android.bp
index abf95a8..16abdbf 100644
--- a/Android.bp
+++ b/Android.bp
@@ -73,6 +73,7 @@
"core/java/android/app/IInstrumentationWatcher.aidl",
"core/java/android/app/INotificationManager.aidl",
"core/java/android/app/IProcessObserver.aidl",
+ "core/java/android/app/IRequestFinishCallback.aidl",
"core/java/android/app/ISearchManager.aidl",
"core/java/android/app/ISearchManagerCallback.aidl",
"core/java/android/app/IServiceConnection.aidl",
@@ -601,6 +602,7 @@
"telephony/java/com/android/ims/ImsConfigListener.aidl",
"telephony/java/com/android/internal/telephony/IApnSourceService.aidl",
"telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl",
+ "telephony/java/com/android/internal/telephony/IIntegerConsumer.aidl",
"telephony/java/com/android/internal/telephony/IMms.aidl",
"telephony/java/com/android/internal/telephony/INumberVerificationCallback.aidl",
"telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl",
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 0015c85..7c21875 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -251,6 +251,7 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/SystemUI)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/DynamicAndroidInstallationService)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/DefaultContainerService)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
# ******************************************************************
diff --git a/apct-tests/perftests/textclassifier/src/android/view/textclassifier/TextClassificationManagerPerfTest.java b/apct-tests/perftests/textclassifier/src/android/view/textclassifier/TextClassificationManagerPerfTest.java
index c149195..bd3b673 100644
--- a/apct-tests/perftests/textclassifier/src/android/view/textclassifier/TextClassificationManagerPerfTest.java
+++ b/apct-tests/perftests/textclassifier/src/android/view/textclassifier/TextClassificationManagerPerfTest.java
@@ -52,7 +52,7 @@
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
textClassificationManager.getTextClassifier();
- textClassificationManager.invalidate();
+ textClassificationManager.invalidateForTesting();
}
}
@@ -68,7 +68,7 @@
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
textClassificationManager.getTextClassifier();
- textClassificationManager.invalidate();
+ textClassificationManager.invalidateForTesting();
}
}
}
diff --git a/api/current.txt b/api/current.txt
index 8b24826..54fb459 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -143,6 +143,7 @@
field public static final String SET_WALLPAPER_HINTS = "android.permission.SET_WALLPAPER_HINTS";
field public static final String SIGNAL_PERSISTENT_PROCESSES = "android.permission.SIGNAL_PERSISTENT_PROCESSES";
field public static final String SMS_FINANCIAL_TRANSACTIONS = "android.permission.SMS_FINANCIAL_TRANSACTIONS";
+ field public static final String START_VIEW_PERMISSION_USAGE = "android.permission.START_VIEW_PERMISSION_USAGE";
field public static final String STATUS_BAR = "android.permission.STATUS_BAR";
field public static final String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";
field public static final String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
@@ -10326,6 +10327,7 @@
field public static final String ACTION_USER_UNLOCKED = "android.intent.action.USER_UNLOCKED";
field public static final String ACTION_VIEW = "android.intent.action.VIEW";
field public static final String ACTION_VIEW_LOCUS = "android.intent.action.VIEW_LOCUS";
+ field @RequiresPermission(android.Manifest.permission.START_VIEW_PERMISSION_USAGE) public static final String ACTION_VIEW_PERMISSION_USAGE = "android.intent.action.VIEW_PERMISSION_USAGE";
field public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
field @Deprecated public static final String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
field public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
diff --git a/api/system-current.txt b/api/system-current.txt
index 36680a1..7c66af5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6401,14 +6401,10 @@
public abstract class ContentSuggestionsService extends android.app.Service {
ctor public ContentSuggestionsService();
- method @Deprecated public void classifyContentSelections(@NonNull android.app.contentsuggestions.ClassificationsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.ClassificationsCallback);
- method @Deprecated public void notifyInteraction(@NonNull String, @NonNull android.os.Bundle);
- method public void onClassifyContentSelections(@NonNull android.app.contentsuggestions.ClassificationsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.ClassificationsCallback);
- method public void onNotifyInteraction(@NonNull String, @NonNull android.os.Bundle);
- method public void onProcessContextImage(int, @Nullable android.graphics.Bitmap, @NonNull android.os.Bundle);
- method public void onSuggestContentSelections(@NonNull android.app.contentsuggestions.SelectionsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.SelectionsCallback);
- method @Deprecated public void processContextImage(int, @Nullable android.graphics.Bitmap, @NonNull android.os.Bundle);
- method @Deprecated public void suggestContentSelections(@NonNull android.app.contentsuggestions.SelectionsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.SelectionsCallback);
+ method public abstract void onClassifyContentSelections(@NonNull android.app.contentsuggestions.ClassificationsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.ClassificationsCallback);
+ method public abstract void onNotifyInteraction(@NonNull String, @NonNull android.os.Bundle);
+ method public abstract void onProcessContextImage(int, @Nullable android.graphics.Bitmap, @NonNull android.os.Bundle);
+ method public abstract void onSuggestContentSelections(@NonNull android.app.contentsuggestions.SelectionsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.SelectionsCallback);
field public static final String SERVICE_INTERFACE = "android.service.contentsuggestions.ContentSuggestionsService";
}
diff --git a/api/test-current.txt b/api/test-current.txt
index aacf2c1..181932c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -725,12 +725,12 @@
field public static final int FLAG_PERMISSION_USER_SET = 1; // 0x1
field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000
- field public static boolean RESTRICTED_PERMISSIONS_ENABLED;
field public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services";
field public static final String SYSTEM_SHARED_LIBRARY_SHARED = "android.ext.shared";
}
public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+ field public static final int FLAG_REMOVED = 2; // 0x2
field public static final int PROTECTION_FLAG_APP_PREDICTOR = 2097152; // 0x200000
field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
@@ -3262,6 +3262,7 @@
ctor public AutofillId(@NonNull android.view.autofill.AutofillId, int);
ctor public AutofillId(int, int);
ctor public AutofillId(@NonNull android.view.autofill.AutofillId, long, int);
+ method public boolean equalsIgnoreSession(@Nullable android.view.autofill.AutofillId);
}
public final class AutofillManager {
@@ -3390,6 +3391,7 @@
package android.view.inputmethod {
public final class InputMethodManager {
+ method public int getDisplayId();
method public boolean isInputMethodPickerShown();
}
diff --git a/cmds/incidentd/Android.bp b/cmds/incidentd/Android.bp
index 534a38f..25e0328 100644
--- a/cmds/incidentd/Android.bp
+++ b/cmds/incidentd/Android.bp
@@ -60,12 +60,6 @@
"libservices",
"libutils",
"libprotobuf-cpp-lite",
- "libcrypto",
- "libkeystore_aidl",
- "libkeystore_binder",
- "libkeystore_parcelables",
- "android.hardware.keymaster@4.0",
- "libkeymaster4support",
],
static_libs: [
@@ -119,8 +113,6 @@
"src/incidentd_util.cpp",
"src/proto_util.cpp",
"src/report_directory.cpp",
- "src/cipher/IncidentKeyStore.cpp",
- "src/cipher/ProtoEncryption.cpp",
"src/**/*.proto",
],
@@ -142,12 +134,6 @@
"libprotoutil",
"libservices",
"libutils",
- "libcrypto",
- "libkeystore_aidl",
- "libkeystore_binder",
- "libkeystore_parcelables",
- "android.hardware.keymaster@4.0",
- "libkeymaster4support",
],
target: {
diff --git a/cmds/incidentd/src/Privacy.cpp b/cmds/incidentd/src/Privacy.cpp
index 0cc358f..0a187e1 100644
--- a/cmds/incidentd/src/Privacy.cpp
+++ b/cmds/incidentd/src/Privacy.cpp
@@ -28,8 +28,6 @@
using namespace android::os;
using std::strstream;
-static const bool kEncryptionEnabled = false;
-
uint64_t encode_field_id(const Privacy* p) { return (uint64_t)p->type << 32 | p->field_id; }
string Privacy::toString() const {
@@ -52,10 +50,6 @@
return NULL;
}
-bool sectionEncryption(int section_id) {
- return kEncryptionEnabled ? (section_id == 3025) /*restricted image section*/ : false;
-}
-
static bool isAllowed(const uint8_t policy, const uint8_t check) {
switch (check) {
case PRIVACY_POLICY_LOCAL:
diff --git a/cmds/incidentd/src/Privacy.h b/cmds/incidentd/src/Privacy.h
index 9cde748..763edb0 100644
--- a/cmds/incidentd/src/Privacy.h
+++ b/cmds/incidentd/src/Privacy.h
@@ -90,9 +90,6 @@
uint8_t mPolicy;
};
-// TODO: Add privacy flag in incident.proto and auto generate it inside Privacy.
-bool sectionEncryption(int section_id);
-
/**
* If a privacy policy is other than the defined values, update it to a real one.
*/
diff --git a/cmds/incidentd/src/PrivacyFilter.cpp b/cmds/incidentd/src/PrivacyFilter.cpp
index ca6fb37..d00ecdd 100644
--- a/cmds/incidentd/src/PrivacyFilter.cpp
+++ b/cmds/incidentd/src/PrivacyFilter.cpp
@@ -16,20 +16,19 @@
#define DEBUG false
#include "Log.h"
+#include "incidentd_util.h"
#include "PrivacyFilter.h"
+#include "proto_util.h"
#include "incidentd_util.h"
#include "proto_util.h"
#include "Section.h"
#include <android-base/file.h>
-#include <android/util/ProtoFileReader.h>
#include <android/util/protobuf.h>
+#include <android/util/ProtoFileReader.h>
#include <log/log.h>
-#include "cipher/IncidentKeyStore.h"
-#include "cipher/ProtoEncryption.h"
-
namespace android {
namespace os {
namespace incidentd {
@@ -146,8 +145,6 @@
*/
status_t writeData(int fd);
- sp<ProtoReader> getData() { return mData; }
-
private:
/**
* The global set of field --> required privacy level mapping.
@@ -259,47 +256,8 @@
mOutputs.push_back(output);
}
-static void write_section_to_file(int sectionId, FieldStripper& fieldStripper, sp<FilterFd> output,
- bool encryptIfNeeded) {
- status_t err;
-
- if (sectionEncryption(sectionId) && encryptIfNeeded) {
- ProtoEncryptor encryptor(fieldStripper.getData());
- size_t encryptedSize = encryptor.encrypt();
-
- if (encryptedSize <= 0) {
- output->onWriteError(BAD_VALUE);
- return;
- }
- err = write_section_header(output->getFd(), sectionId, encryptedSize);
- VLOG("Encrypted: write section header size %lu", (unsigned long)encryptedSize);
-
- encryptor.flush(output->getFd());
-
- if (err != NO_ERROR) {
- output->onWriteError(err);
- return;
- }
- } else {
- err = write_section_header(output->getFd(), sectionId, fieldStripper.dataSize());
- VLOG("No encryption: write section header size %lu",
- (unsigned long)fieldStripper.dataSize());
-
- if (err != NO_ERROR) {
- output->onWriteError(err);
- return;
- }
-
- err = fieldStripper.writeData(output->getFd());
- if (err != NO_ERROR) {
- output->onWriteError(err);
- return;
- }
- }
-}
-
-status_t PrivacyFilter::writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize,
- bool encryptIfNeeded) {
+status_t PrivacyFilter::writeData(const FdBuffer& buffer, uint8_t bufferLevel,
+ size_t* maxSize) {
status_t err;
if (maxSize != NULL) {
@@ -309,9 +267,9 @@
// Order the writes by privacy filter, with increasing levels of filtration,k
// so we can do the filter once, and then write many times.
sort(mOutputs.begin(), mOutputs.end(),
- [](const sp<FilterFd>& a, const sp<FilterFd>& b) -> bool {
- return a->getPrivacyPolicy() < b->getPrivacyPolicy();
- });
+ [](const sp<FilterFd>& a, const sp<FilterFd>& b) -> bool {
+ return a->getPrivacyPolicy() < b->getPrivacyPolicy();
+ });
uint8_t privacyPolicy = PRIVACY_POLICY_LOCAL; // a.k.a. no filtering
FieldStripper fieldStripper(mRestrictions, buffer.data()->read(), bufferLevel);
@@ -330,7 +288,17 @@
// Write the resultant buffer to the fd, along with the header.
ssize_t dataSize = fieldStripper.dataSize();
if (dataSize > 0) {
- write_section_to_file(mSectionId, fieldStripper, output, encryptIfNeeded);
+ err = write_section_header(output->getFd(), mSectionId, dataSize);
+ if (err != NO_ERROR) {
+ output->onWriteError(err);
+ continue;
+ }
+
+ err = fieldStripper.writeData(output->getFd());
+ if (err != NO_ERROR) {
+ output->onWriteError(err);
+ continue;
+ }
}
if (maxSize != NULL) {
@@ -382,18 +350,8 @@
// Read this section from the reader into an FdBuffer
size_t sectionSize = reader->readRawVarint();
-
FdBuffer sectionData;
-
- // Write data to FdBuffer, if the section was encrypted, decrypt first.
- if (sectionEncryption(fieldId)) {
- VLOG("sectionSize %lu", (unsigned long)sectionSize);
- ProtoDecryptor decryptor(reader, sectionSize);
- err = decryptor.decryptAndFlush(§ionData);
- } else {
- err = sectionData.write(reader, sectionSize);
- }
-
+ err = sectionData.write(reader, sectionSize);
if (err != NO_ERROR) {
ALOGW("filter_and_write_report FdBuffer.write failed (this shouldn't happen): %s",
strerror(-err));
@@ -401,8 +359,7 @@
}
// Do the filter and write.
- err = filter.writeData(sectionData, bufferLevel, nullptr,
- false /* do not encrypt again*/);
+ err = filter.writeData(sectionData, bufferLevel, nullptr);
if (err != NO_ERROR) {
ALOGW("filter_and_write_report filter.writeData had an error: %s", strerror(-err));
return err;
@@ -411,7 +368,6 @@
// We don't need this field. Incident does not have any direct children
// other than sections. So just skip them.
write_field_or_skip(NULL, reader, fieldTag, true);
- VLOG("Skip this.... section %d", fieldId);
}
}
diff --git a/cmds/incidentd/src/PrivacyFilter.h b/cmds/incidentd/src/PrivacyFilter.h
index d426db9..76b2849 100644
--- a/cmds/incidentd/src/PrivacyFilter.h
+++ b/cmds/incidentd/src/PrivacyFilter.h
@@ -82,14 +82,8 @@
* was written (i.e. after filtering).
*
* The buffer is assumed to have already been filtered to bufferLevel.
- *
- * This function can be called when persisting data to disk or when sending
- * data to client. In the former case, we need to encrypt the data when that
- * section requires encryption. In the latter case, we shouldn't send the
- * unencrypted data to client.
*/
- status_t writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize,
- bool encryptIfNeeded);
+ status_t writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize);
private:
int mSectionId;
diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp
index dc4065b..02b6bbe 100644
--- a/cmds/incidentd/src/Reporter.cpp
+++ b/cmds/incidentd/src/Reporter.cpp
@@ -465,8 +465,7 @@
}
});
- return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize,
- true /*encrypt if needed*/);
+ return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize);
}
diff --git a/cmds/incidentd/src/cipher/IncidentKeyStore.cpp b/cmds/incidentd/src/cipher/IncidentKeyStore.cpp
deleted file mode 100644
index ae0a920..0000000
--- a/cmds/incidentd/src/cipher/IncidentKeyStore.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open 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 "Log.h"
-
-#include "IncidentKeyStore.h"
-
-#include <sys/stat.h>
-
-static constexpr size_t AES_KEY_BYTES = 32;
-static constexpr size_t GCM_MAC_BYTES = 16;
-constexpr char kKeyname[] = "IncidentKey";
-
-namespace android {
-namespace os {
-namespace incidentd {
-
-using namespace keystore;
-using std::string;
-
-IncidentKeyStore& IncidentKeyStore::getInstance() {
- static IncidentKeyStore sInstance(new keystore::KeystoreClientImpl);
- return sInstance;
-}
-
-bool IncidentKeyStore::encrypt(const string& data, int32_t flags, string* output) {
- std::lock_guard<std::mutex> lock(mMutex);
- if (data.empty()) {
- ALOGW("IncidentKeyStore: Encrypt empty data?!");
- return false;
- }
- if (!mClient->doesKeyExist(kKeyname)) {
- auto gen_result = generateKeyLocked(kKeyname, 0);
- if (!gen_result.isOk()) {
- ALOGE("IncidentKeyStore: Key generate failed.");
- return false;
- }
- }
- if (!mClient->encryptWithAuthentication(kKeyname, data, flags, output)) {
- ALOGE("IncidentKeyStore: Encryption failed.");
- return false;
- }
- return true;
-}
-
-bool IncidentKeyStore::decrypt(const std::string& input, string* output) {
- std::lock_guard<std::mutex> lock(mMutex);
- if (input.empty()) {
- ALOGE("IncidentKeyStore: Decrypt empty input?");
- return false;
- }
- if (!mClient->decryptWithAuthentication(kKeyname, input, output)) {
- ALOGE("IncidentKeyStore: Decryption failed.");
- return false;
- }
- return true;
-}
-
-KeyStoreNativeReturnCode IncidentKeyStore::generateKeyLocked(const std::string& name,
- int32_t flags) {
- auto paramBuilder = AuthorizationSetBuilder()
- .AesEncryptionKey(AES_KEY_BYTES * 8)
- .GcmModeMinMacLen(GCM_MAC_BYTES * 8)
- .Authorization(TAG_NO_AUTH_REQUIRED);
-
- AuthorizationSet hardware_enforced_characteristics;
- AuthorizationSet software_enforced_characteristics;
- return mClient->generateKey(name, paramBuilder, flags, &hardware_enforced_characteristics,
- &software_enforced_characteristics);
-}
-
-} // namespace incidentd
-} // namespace os
-} // namespace android
diff --git a/cmds/incidentd/src/cipher/IncidentKeyStore.h b/cmds/incidentd/src/cipher/IncidentKeyStore.h
deleted file mode 100644
index 27611cd..0000000
--- a/cmds/incidentd/src/cipher/IncidentKeyStore.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <keystore/keystore_client_impl.h>
-
-namespace android {
-namespace os {
-namespace incidentd {
-
-class IncidentKeyStore {
-public:
- static IncidentKeyStore& getInstance();
-
- IncidentKeyStore(keystore::KeystoreClient* client) : mClient(client) {}
-
- /**
- * Encrypt the plainText and output the encrypted message.
- *
- * Returns true on success and false otherwise.
- * If the key has not been created yet, it will generate the key in KeyMaster.
- */
- bool encrypt(const std::string& plainText, int32_t flags, std::string* output);
-
- /**
- * Decrypt and output the decrypted message.
- *
- * Returns true on success and false otherwise.
- */
- bool decrypt(const std::string& encryptedData, std::string* output);
-
-private:
- std::unique_ptr<keystore::KeystoreClient> mClient;
- std::mutex mMutex;
- keystore::KeyStoreNativeReturnCode generateKeyLocked(const std::string& name, int32_t flags);
-};
-
-} // namespace incidentd
-} // namespace os
-} // namespace android
diff --git a/cmds/incidentd/src/cipher/ProtoEncryption.cpp b/cmds/incidentd/src/cipher/ProtoEncryption.cpp
deleted file mode 100644
index 493796d..0000000
--- a/cmds/incidentd/src/cipher/ProtoEncryption.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open 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.
- */
-
-#define DEBUG true // STOPSHIP if true
-#include "Log.h"
-
-#include "ProtoEncryption.h"
-
-#include <android/util/protobuf.h>
-
-#include "IncidentKeyStore.h"
-
-namespace android {
-namespace os {
-namespace incidentd {
-
-using android::util::FIELD_COUNT_REPEATED;
-using android::util::FIELD_TYPE_STRING;
-using android::util::ProtoOutputStream;
-using android::util::ProtoReader;
-using std::string;
-
-static const int FIELD_ID_BLOCK = 1;
-
-size_t ProtoEncryptor::encrypt() {
- string block;
- int i = 0;
- // Read at most sBlockSize at a time and encrypt.
- while (mReader->readBuffer() != NULL) {
- size_t readBytes =
- mReader->currentToRead() > sBlockSize ? sBlockSize : mReader->currentToRead();
- block.resize(readBytes);
- std::memcpy(block.data(), mReader->readBuffer(), readBytes);
-
- string encrypted;
- if (IncidentKeyStore::getInstance().encrypt(block, 0, &encrypted)) {
- mOutputStream.write(FIELD_TYPE_STRING | FIELD_ID_BLOCK | FIELD_COUNT_REPEATED,
- encrypted);
- VLOG("Block %d Encryption: original %lld now %lld", i++, (long long)readBytes,
- (long long)encrypted.length());
- mReader->move(readBytes);
- } else {
- return 0;
- }
- }
- return mOutputStream.size();
-}
-
-status_t ProtoEncryptor::flush(int fd) {
- if (!mOutputStream.flush(fd)) {
- return BAD_VALUE;
- }
- return NO_ERROR;
-}
-
-status_t ProtoDecryptor::readOneBlock(string* output) {
- if (!mReader->hasNext()) {
- return NO_ERROR;
- }
- uint64_t fieldTag = mReader->readRawVarint();
- uint32_t fieldId = read_field_id(fieldTag);
- uint8_t wireType = read_wire_type(fieldTag);
- if (wireType == WIRE_TYPE_LENGTH_DELIMITED) {
- // Read this section from the reader into an FdBuffer
- size_t sectionSize = mReader->readRawVarint();
- output->resize(sectionSize);
- size_t pos = 0;
- while (pos < sectionSize && mReader->readBuffer() != NULL) {
- size_t toRead = (sectionSize - pos) > mReader->currentToRead()
- ? mReader->currentToRead()
- : (sectionSize - pos);
- std::memcpy(&((output->data())[pos]), mReader->readBuffer(), toRead);
- pos += toRead;
- mReader->move(toRead);
- }
- if (pos != sectionSize) {
- return BAD_VALUE;
- ALOGE("Failed to read one block");
- }
- } else {
- return BAD_VALUE;
- }
- return NO_ERROR;
-}
-
-status_t ProtoDecryptor::decryptAndFlush(FdBuffer* out) {
- size_t mStartBytes = mReader->bytesRead();
- size_t bytesRead = 0;
- int i = 0;
- status_t err = NO_ERROR;
- // Let's read until we read mTotalSize. If any error occurs before that, make sure to move the
- // read pointer so the caller can continue to read the following sections.
- while (bytesRead < mTotalSize) {
- string block;
- err = readOneBlock(&block);
- bytesRead = mReader->bytesRead() - mStartBytes;
-
- if (err != NO_ERROR) {
- break;
- }
-
- if (block.length() == 0) {
- VLOG("Done reading all blocks");
- break;
- }
-
- string decryptedBlock;
- if ((IncidentKeyStore::getInstance()).decrypt(block, &decryptedBlock)) {
- VLOG("Block %d Original Size %lu Decrypted size %lu", i++,
- (unsigned long)block.length(), (unsigned long)decryptedBlock.length());
- out->write(reinterpret_cast<uint8_t*>(decryptedBlock.data()), decryptedBlock.length());
- } else {
- err = BAD_VALUE;
- break;
- }
- }
-
- if (bytesRead < mTotalSize) {
- mReader->move(mTotalSize - bytesRead);
- }
- return err;
-}
-
-} // namespace incidentd
-} // namespace os
-} // namespace android
diff --git a/cmds/incidentd/src/cipher/ProtoEncryption.h b/cmds/incidentd/src/cipher/ProtoEncryption.h
deleted file mode 100644
index 5b72ca8..0000000
--- a/cmds/incidentd/src/cipher/ProtoEncryption.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <android/util/ProtoOutputStream.h>
-#include <android/util/ProtoReader.h>
-#include <frameworks/base/cmds/incidentd/src/cipher/cipher_blocks.pb.h>
-
-#include "FdBuffer.h"
-
-namespace android {
-namespace os {
-namespace incidentd {
-
-// PlainText IncidentReport format
-// [section1_header(id, size, type)][section1_data] ...
-
-// Let's say section1 needs encryption
-// After encryption, it becomes
-// [section1_header(id, encrypted_size, type)][[cipher_block][cipher_block][cipher_block]..]
-
-// When clients read the report, it's decrypted, and written in its original format
-
-/**
- * Takes a ProtoReader, encrypts its whole content -- which is one section, and flush to
- * a file descriptor.
- * The underlying encryption is done using Keystore binder APIs. We encrypt the data
- * in blocks, and write to the file in android.os.incidentd.CipherBlocks format.
- */
-class ProtoEncryptor {
-public:
- ProtoEncryptor(const sp<android::util::ProtoReader>& reader) : mReader(reader){};
-
- // Encrypt the data from ProtoReader, and store in CipherBlocks format.
- // return the size of CipherBlocks.
- size_t encrypt();
-
- status_t flush(int fd);
-
-private:
- static const size_t sBlockSize = 8 * 1024;
- const sp<android::util::ProtoReader> mReader;
- android::util::ProtoOutputStream mOutputStream;
-};
-
-// Read data from ProtoReader, which is in CipherBlocks proto format. Parse and decrypt
-// block by block.
-class ProtoDecryptor {
-public:
- ProtoDecryptor(const sp<android::util::ProtoReader>& reader, size_t size)
- : mReader(reader), mTotalSize(size){};
- status_t decryptAndFlush(FdBuffer* out);
-
-private:
- const sp<android::util::ProtoReader> mReader;
-
- // Total size in bytes we should read from ProtoReader.
- const size_t mTotalSize;
-
- // Read one cipher block from ProtoReader, instead of reading the whole content
- // and parse to CipherBlocks which could be huge.
- status_t readOneBlock(std::string* output);
-};
-
-} // namespace incidentd
-} // namespace os
-} // namespace android
diff --git a/cmds/incidentd/tests/IncidentKeyStore_test.cpp b/cmds/incidentd/tests/IncidentKeyStore_test.cpp
deleted file mode 100644
index 2250fda..0000000
--- a/cmds/incidentd/tests/IncidentKeyStore_test.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open 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 "cipher/IncidentKeyStore.h"
-
-#include <binder/ProcessState.h>
-#include <gtest/gtest.h>
-
-#include <fstream>
-
-using namespace android::os::incidentd;
-
-class IncidentKeyStoreTest : public ::testing::Test {
-protected:
- std::unique_ptr<IncidentKeyStore> incidentKeyStore;
- void SetUp() override {
- android::ProcessState::self()->startThreadPool();
- incidentKeyStore = std::make_unique<IncidentKeyStore>(
- static_cast<keystore::KeystoreClient*>(new keystore::KeystoreClientImpl));
- };
- void TearDown() override { incidentKeyStore = nullptr; };
-};
-
-TEST_F(IncidentKeyStoreTest, test_encrypt_decrypt) {
- std::string plaintext;
- plaintext.resize(4 * 1024, 'a');
-
- std::string encrypted;
- EXPECT_TRUE(incidentKeyStore->encrypt(plaintext, 0, &encrypted));
- std::string decrypted;
- EXPECT_TRUE(incidentKeyStore->decrypt(encrypted, &decrypted));
-
- EXPECT_FALSE(encrypted.empty());
- EXPECT_EQ(plaintext, decrypted);
-}
-
-TEST_F(IncidentKeyStoreTest, test_encrypt_empty_hash) {
- std::string hash = "";
-
- std::string encrypted;
- EXPECT_FALSE(incidentKeyStore->encrypt(hash, 0, &encrypted));
-
- EXPECT_TRUE(encrypted.empty());
-}
-
-TEST_F(IncidentKeyStoreTest, test_decrypt_empty_hash) {
- std::string hash = "";
-
- std::string decrypted;
- EXPECT_FALSE(incidentKeyStore->decrypt(hash, &decrypted));
-
- EXPECT_TRUE(decrypted.empty());
-}
\ No newline at end of file
diff --git a/cmds/incidentd/tests/ProtoEncryption_test.cpp b/cmds/incidentd/tests/ProtoEncryption_test.cpp
deleted file mode 100644
index 6742e03..0000000
--- a/cmds/incidentd/tests/ProtoEncryption_test.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open 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 "Log.h"
-
-#include "cipher/ProtoEncryption.h"
-
-#include <android-base/file.h>
-#include <gtest/gtest.h>
-
-#include "FdBuffer.h"
-#include "android/util/ProtoFileReader.h"
-
-using namespace android::os::incidentd;
-using android::sp;
-using std::string;
-using ::testing::Test;
-
-const std::string kTestPath = GetExecutableDirectory();
-const std::string kTestDataPath = kTestPath + "/testdata/";
-
-TEST(ProtoEncryptionTest, test_encrypt_decrypt) {
- const std::string plaintextFile = kTestDataPath + "plaintext.txt";
- const std::string encryptedFile = kTestDataPath + "encrypted.txt";
- size_t msg1Size = 20 * 1024;
-
- // Create a file with plain text.
- {
- unique_fd fd(
- open(plaintextFile.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR));
- ASSERT_NE(fd.get(), -1);
- string content;
- content.resize(msg1Size, 'a');
- WriteFully(fd, content.data(), msg1Size);
- }
-
- // Read the plain text and encrypted
- {
- unique_fd readFd(open(plaintextFile.c_str(), O_RDONLY | O_CLOEXEC));
- unique_fd encryptedFd(
- open(encryptedFile.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR));
-
- ASSERT_NE(readFd.get(), -1);
- ASSERT_NE(encryptedFd.get(), -1);
-
- sp<ProtoFileReader> reader = new ProtoFileReader(readFd.get());
- ProtoEncryptor encryptor(reader);
- EXPECT_TRUE(encryptor.encrypt() > msg1Size);
-
- encryptor.flush(encryptedFd.get());
- }
-
- // Read the encrypted file, and decrypt
- unique_fd encryptedFd(open(encryptedFile.c_str(), O_RDONLY | O_CLOEXEC));
- ASSERT_NE(encryptedFd.get(), -1);
- FdBuffer output;
- sp<ProtoFileReader> reader2 = new ProtoFileReader(encryptedFd.get());
- ProtoDecryptor decryptor(reader2, reader2->size());
- decryptor.decryptAndFlush(&output);
-
- auto decryptedReader = output.data()->read();
-
- // Check the content.
- int count = 0;
- while (decryptedReader->hasNext()) {
- if (decryptedReader->next() == 'a') {
- count++;
- }
- }
-
- EXPECT_EQ(msg1Size, count);
-}
\ No newline at end of file
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index c497667..0bb1af1 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -86,20 +86,6 @@
}
}
-static ui::Dataspace pickBestDataspace(ui::ColorMode colorMode)
-{
- switch (colorMode) {
- case ui::ColorMode::SRGB:
- return ui::Dataspace::V0_SRGB;
- case ui::ColorMode::DISPLAY_P3:
- case ui::ColorMode::BT2100_PQ:
- case ui::ColorMode::BT2100_HLG:
- return ui::Dataspace::DISPLAY_P3;
- default:
- return ui::Dataspace::V0_SRGB;
- }
-}
-
static uint32_t dataSpaceToInt(ui::Dataspace d)
{
switch (d) {
@@ -181,14 +167,6 @@
uint32_t w, s, h, f;
size_t size = 0;
- // Maps orientations from DisplayInfo to ISurfaceComposer
- static const uint32_t ORIENTATION_MAP[] = {
- ISurfaceComposer::eRotateNone, // 0 == DISPLAY_ORIENTATION_0
- ISurfaceComposer::eRotate270, // 1 == DISPLAY_ORIENTATION_90
- ISurfaceComposer::eRotate180, // 2 == DISPLAY_ORIENTATION_180
- ISurfaceComposer::eRotate90, // 3 == DISPLAY_ORIENTATION_270
- };
-
// setThreadPoolMaxThreadCount(0) actually tells the kernel it's
// not allowed to spawn any additional threads, but we still spawn
// a binder thread from userspace when we call startThreadPool().
@@ -196,34 +174,10 @@
ProcessState::self()->setThreadPoolMaxThreadCount(0);
ProcessState::self()->startThreadPool();
- const sp<IBinder> display = SurfaceComposerClient::getPhysicalDisplayToken(*displayId);
- if (display == nullptr) {
- fprintf(stderr, "Failed to get token for invalid display %"
- ANDROID_PHYSICAL_DISPLAY_ID_FORMAT "\n", *displayId);
- return 1;
- }
-
- Vector<DisplayInfo> configs;
- SurfaceComposerClient::getDisplayConfigs(display, &configs);
- int activeConfig = SurfaceComposerClient::getActiveConfig(display);
- if (static_cast<size_t>(activeConfig) >= configs.size()) {
- fprintf(stderr, "Active config %d not inside configs (size %zu)\n",
- activeConfig, configs.size());
- return 1;
- }
- uint8_t displayOrientation = configs[activeConfig].orientation;
- uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation];
-
+ ui::Dataspace outDataspace;
sp<GraphicBuffer> outBuffer;
- ui::Dataspace reqDataspace =
- pickBestDataspace(SurfaceComposerClient::getActiveColorMode(display));
- // Due to the fact that we hard code the way we write pixels into screenshot,
- // we hard code RGBA_8888 here.
- ui::PixelFormat reqPixelFormat = ui::PixelFormat::RGBA_8888;
- status_t result = ScreenshotClient::capture(display, reqDataspace, reqPixelFormat, Rect(),
- 0 /* reqWidth */, 0 /* reqHeight */, false,
- captureOrientation, &outBuffer);
+ status_t result = ScreenshotClient::capture(*displayId, &outDataspace, &outBuffer);
if (result != NO_ERROR) {
close(fd);
return 1;
@@ -233,10 +187,10 @@
if (base == nullptr || result != NO_ERROR) {
String8 reason;
- if (base == nullptr) {
- reason = "Failed to write to buffer";
+ if (result != NO_ERROR) {
+ reason.appendFormat(" Error Code: %d", result);
} else {
- reason.appendFormat("Error Code: %d", result);
+ reason = "Failed to write to buffer";
}
fprintf(stderr, "Failed to take screenshot (%s)\n", reason.c_str());
close(fd);
@@ -252,7 +206,7 @@
if (png) {
const SkImageInfo info =
SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType,
- dataSpaceToColorSpace(reqDataspace));
+ dataSpaceToColorSpace(outDataspace));
SkPixmap pixmap(info, base, s * bytesPerPixel(f));
struct FDWStream final : public SkWStream {
size_t fBytesWritten = 0;
@@ -269,7 +223,7 @@
notifyMediaScanner(fn);
}
} else {
- uint32_t c = dataSpaceToInt(reqDataspace);
+ uint32_t c = dataSpaceToInt(outDataspace);
write(fd, &w, 4);
write(fd, &h, 4);
write(fd, &f, 4);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 3a84b79..f53ac1b 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -41,7 +41,7 @@
import "frameworks/base/core/proto/android/service/procstats_enum.proto";
import "frameworks/base/core/proto/android/service/usb.proto";
import "frameworks/base/core/proto/android/stats/connectivity/network_stack.proto";
-import "frameworks/base/core/proto/android/stats/connectivity/resolv_stats.proto";
+import "frameworks/base/core/proto/android/stats/dnsresolver/dns_resolver.proto";
import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy.proto";
import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy_enums.proto";
import "frameworks/base/core/proto/android/stats/docsui/docsui_enums.proto";
@@ -294,6 +294,11 @@
MediametricsMediadrmReported mediametrics_mediadrm_reported = 198;
MediametricsNuPlayerReported mediametrics_nuplayer_reported = 199;
MediametricsRecorderReported mediametrics_recorder_reported = 200;
+ VehicleMapServicePacketReported vms_packet_reported = 201;
+ VehicleMapServicePacketFailureReported vms_packet_failure_reported = 202;
+ CarPowerStateChanged car_power_state_changed = 203;
+ GarageModeInfo garage_mode_info = 204;
+ TestAtomReported test_atom_reported = 205 [(log_from_module) = "cts"];
}
// Pulled events will start at field 10000.
@@ -3338,6 +3343,23 @@
optional int32 user_id = 8;
}
+/* Test atom, is not logged anywhere */
+message TestAtomReported {
+ repeated AttributionNode attribution_node = 1;
+ optional int32 int_field = 2;
+ optional int64 long_field = 3;
+ optional float float_field = 4;
+ optional string string_field = 5;
+ optional bool boolean_field = 6;
+ enum State {
+ UNKNOWN = 0;
+ OFF = 1;
+ ON = 2;
+ }
+ optional State state = 7;
+ optional TrainExperimentIds bytes_field = 8 [(android.os.statsd.log_mode) = MODE_BYTES];
+}
+
/** Represents USB port overheat event. */
message UsbPortOverheatEvent {
/* Temperature of USB port at USB plug event, in 1/10ths of degree C. */
@@ -5109,36 +5131,36 @@
* Logs a DNS lookup operation initiated by the system resolver on behalf of an application
* invoking native APIs such as getaddrinfo() or Java APIs such as Network#getAllByName().
*
- * The top-level message represents the entire lookup operation, which may result one or more
- * queries to the recursive DNS resolvers. Those are individually logged in DnsQueryEvent to
- * enable computing error rates and network latency and timeouts broken up by query type,
- * transport, network interface, etc.
+ * The NetworkDnsEventReported message represents the entire lookup operation, which may
+ * result one or more queries to the recursive DNS resolvers. Those are individually logged
+ * in DnsQueryEvents to enable computing error rates and network latency and timeouts
+ * broken up by query type, transport, network interface, etc.
*/
message NetworkDnsEventReported {
+ optional android.stats.dnsresolver.EventType event_type = 1;
- optional android.stats.connectivity.EventType event_type = 1;
-
- optional android.stats.connectivity.ReturnCode return_code = 2;
+ optional android.stats.dnsresolver.ReturnCode return_code = 2;
// The latency in microseconds of the entire DNS lookup operation.
optional int32 latency_micros = 3;
- optional android.stats.connectivity.DnsQueryEventRe dns_query_event_re = 4 [(log_mode) = MODE_BYTES];
+ // Only valid for event_type = EVENT_GETADDRINFO.
+ optional int32 hints_ai_flags = 4;
- // ResNSend flags defined in android/multinetwork.h
- optional int32 flags = 5;
+ // Flags passed to android_res_nsend() defined in multinetwork.h
+ // Only valid for event_type = EVENT_RESNSEND.
+ optional int32 res_nsend_flags = 5;
- optional android.net.NetworkCapabilitiesProto.Transport network_type = 6;
+ optional android.stats.dnsresolver.Transport network_type = 6;
// The DNS over TLS mode on a specific netId.
- optional android.stats.connectivity.PrivateDnsModes private_dns_modes = 7;
+ optional android.stats.dnsresolver.PrivateDnsModes private_dns_modes = 7;
// Additional pass-through fields opaque to statsd.
// The DNS resolver Mainline module can add new fields here without requiring an OS update.
- optional android.stats.connectivity.DnsCallEvent dns_call_event = 8 [(log_mode) = MODE_BYTES];
+ optional android.stats.dnsresolver.DnsQueryEvents dns_query_events = 8 [(log_mode) = MODE_BYTES];
}
-
/**
* Logs when a data stall event occurs.
*
@@ -6131,6 +6153,21 @@
// Total count of the Vulkan driver fails to be loaded.
optional int64 vk_loading_failure_count = 8;
+
+ // Api version of the system Vulkan driver.
+ optional int32 vulkan_version = 9;
+
+ // Api version of the system CPU Vulkan driver.
+ optional int32 cpu_vulkan_version = 10;
+
+ // Api version of the system GLES driver.
+ optional int32 gles_version = 11;
+
+ // Total count of the angle driver gets loaded.
+ optional int64 angle_loading_count = 12;
+
+ // Total count of the angle driver fails to be loaded.
+ optional int64 angle_loading_failure_count = 13;
}
/**
@@ -6163,6 +6200,13 @@
// Vulkan driver loading time info.
optional GpuDriverLoadingTime vk_driver_loading_time = 4
[(android.os.statsd.log_mode) = MODE_BYTES];
+
+ // Angle driver loading time info.
+ optional GpuDriverLoadingTime angle_driver_loading_time = 5
+ [(android.os.statsd.log_mode) = MODE_BYTES];
+
+ // CPU Vulkan implementation is in use.
+ optional bool cpu_vulkan_in_use = 6;
}
/*
@@ -6247,3 +6291,69 @@
optional android.stats.intelligence.EventType event_id = 1;
optional android.stats.intelligence.Status status = 2;
}
+
+/**
+ * Logs information about Vehicle Map Service packets. It specifies the layer
+ * type, subtype, data version and size of the packet.
+ */
+message VehicleMapServicePacketReported {
+ // Identifies the type of data being transported by a Vehicle Maps Service
+ // packet.
+ optional int32 layer_type = 1;
+ // Identifies the subtype of the layer.
+ optional int32 layer_subtype = 2;
+ // Identifies the version of the data being transported by a Vehicle Maps
+ // Service packet.
+ optional int32 version = 3;
+ // Size in bytes of the packet.
+ optional int64 size_in_bytes = 4;
+}
+
+/**
+ * Logs that a Vehicle Map Service packet failed to be delivered.
+ */
+message VehicleMapServicePacketFailureReported {
+ // Identifies the type of data being transported by a Vehicle Map Service
+ // packet.
+ optional int32 layer_type = 1;
+ // Identifies the subtype of the layer.
+ optional int32 layer_subtype = 2;
+ // Identifies the version of the data being transported by a Vehicle Map
+ // Service packet.
+ optional int32 version = 3;
+ // Identifies the package name of the publisher of the data.
+ optional string publisher_name = 4;
+ // Identifies the package name of the subscriber of the data. An empty string
+ // signifies that there are zero subscribers for the packet.
+ optional string subscriber_name = 5;
+}
+
+/**
+ * Logs when Car Power state changed.
+ *
+ * Logged from:
+ * packages/services/Car/service/src/com/android/car/CarStatsLog.java
+ */
+message CarPowerStateChanged {
+ // States come from CpmsState in CarPowerManagementService.java.
+ enum State {
+ WAIT_FOR_VHAL = 0;
+ ON = 1;
+ SHUTDOWN_PREPARE = 2;
+ WAIT_FOR_FINISH = 3;
+ SUSPEND = 4;
+ SIMULATE_SLEEP = 5;
+ }
+ optional State state = 1;
+}
+
+/**
+ * Logs whether GarageMode is entered.
+ *
+ * Logged from:
+ * packages/services/Car/service/src/com/android/car/CarStatsLog.java
+ */
+message GarageModeInfo {
+ // Whether GarageMode is entered.
+ optional bool is_garage_mode = 1;
+}
diff --git a/cmds/statsd/src/external/GpuStatsPuller.cpp b/cmds/statsd/src/external/GpuStatsPuller.cpp
index 3fa932f..0d3aca0 100644
--- a/cmds/statsd/src/external/GpuStatsPuller.cpp
+++ b/cmds/statsd/src/external/GpuStatsPuller.cpp
@@ -65,6 +65,11 @@
if (!event->write((int64_t)info.glLoadingFailureCount)) return false;
if (!event->write((int64_t)info.vkLoadingCount)) return false;
if (!event->write((int64_t)info.vkLoadingFailureCount)) return false;
+ if (!event->write(info.vulkanVersion)) return false;
+ if (!event->write(info.cpuVulkanVersion)) return false;
+ if (!event->write(info.glesVersion)) return false;
+ if (!event->write((int64_t)info.angleLoadingCount)) return false;
+ if (!event->write((int64_t)info.angleLoadingFailureCount)) return false;
event->init();
data->emplace_back(event);
}
@@ -89,6 +94,8 @@
if (!event->write((int64_t)info.driverVersionCode)) return false;
if (!event->write(int64VectorToProtoByteString(info.glDriverLoadingTime))) return false;
if (!event->write(int64VectorToProtoByteString(info.vkDriverLoadingTime))) return false;
+ if (!event->write(int64VectorToProtoByteString(info.angleDriverLoadingTime))) return false;
+ if (!event->write(info.cpuVulkanInUse)) return false;
event->init();
data->emplace_back(event);
}
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 74a4c87..ce0e561 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -432,12 +432,13 @@
void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) {
lock_guard<std::mutex> lock(mLock);
- if (atomId > android::util::kMaxPushedAtomId) {
- ALOGW("not interested in atom %d", atomId);
- return;
+ if (atomId <= android::util::kMaxPushedAtomId) {
+ mPushedAtomStats[atomId]++;
+ } else {
+ if (mNonPlatformPushedAtomStats.size() < kMaxNonPlatformPushedAtoms) {
+ mNonPlatformPushedAtomStats[atomId]++;
+ }
}
-
- mPushedAtomStats[atomId]++;
}
void StatsdStats::noteSystemServerRestart(int32_t timeSec) {
@@ -551,6 +552,7 @@
mStartTimeSec = getWallClockSec();
mIceBox.clear();
std::fill(mPushedAtomStats.begin(), mPushedAtomStats.end(), 0);
+ mNonPlatformPushedAtomStats.clear();
mAnomalyAlarmRegisteredStats = 0;
mPeriodicAlarmRegisteredStats = 0;
mSystemServerRestartSec.clear();
@@ -705,6 +707,9 @@
dprintf(out, "Atom %lu->%d\n", (unsigned long)i, mPushedAtomStats[i]);
}
}
+ for (const auto& pair : mNonPlatformPushedAtomStats) {
+ dprintf(out, "Atom %lu->%d\n", (unsigned long)pair.first, pair.second);
+ }
dprintf(out, "********Pulled Atom stats***********\n");
for (const auto& pair : mPulledAtomStats) {
@@ -890,6 +895,14 @@
}
}
+ for (const auto& pair : mNonPlatformPushedAtomStats) {
+ uint64_t token =
+ proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM_STATS | FIELD_COUNT_REPEATED);
+ proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_TAG, pair.first);
+ proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_COUNT, pair.second);
+ proto.end(token);
+ }
+
for (const auto& pair : mPulledAtomStats) {
android::os::statsd::writePullerStatsToStream(pair, &proto);
}
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 4d21a29..8b39f5f 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -24,6 +24,7 @@
#include <mutex>
#include <string>
#include <vector>
+#include <unordered_map>
namespace android {
namespace os {
@@ -160,6 +161,9 @@
// Max time to do a pull.
static const int64_t kPullMaxDelayNs = 10 * NS_PER_SEC;
+ // Maximum number of pushed atoms statsd stats will track above kMaxPushedAtomId.
+ static const int kMaxNonPlatformPushedAtoms = 100;
+
// Max platform atom tag number.
static const int32_t kMaxPlatformAtomTag = 100000;
@@ -508,10 +512,14 @@
// Stores the number of times a pushed atom is logged.
// The size of the vector is the largest pushed atom id in atoms.proto + 1. Atoms
- // out of that range will be dropped (it's either pulled atoms or test atoms).
+ // out of that range will be put in mNonPlatformPushedAtomStats.
// This is a vector, not a map because it will be accessed A LOT -- for each stats log.
std::vector<int> mPushedAtomStats;
+ // Stores the number of times a pushed atom is logged for atom ids above kMaxPushedAtomId.
+ // The max size of the map is kMaxNonPlatformPushedAtoms.
+ std::unordered_map<int, int> mNonPlatformPushedAtomStats;
+
// Maps PullAtomId to its stats. The size is capped by the puller atom counts.
std::map<int, PulledAtomStats> mPulledAtomStats;
@@ -587,6 +595,7 @@
FRIEND_TEST(StatsdStatsTest, TestConfigRemove);
FRIEND_TEST(StatsdStatsTest, TestSubStats);
FRIEND_TEST(StatsdStatsTest, TestAtomLog);
+ FRIEND_TEST(StatsdStatsTest, TestNonPlatformAtomLog);
FRIEND_TEST(StatsdStatsTest, TestTimestampThreshold);
FRIEND_TEST(StatsdStatsTest, TestAnomalyMonitor);
FRIEND_TEST(StatsdStatsTest, TestSystemServerCrash);
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 49fe7ef..41000da 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -312,7 +312,7 @@
}
}
-void GaugeMetricProducer::prepareFistBucketLocked() {
+void GaugeMetricProducer::prepareFirstBucketLocked() {
if (mIsActive && mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index d3007c8..1b43d43 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -122,7 +122,7 @@
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
- void prepareFistBucketLocked() override;
+ void prepareFirstBucketLocked() override;
void pullAndMatchEventsLocked(const int64_t timestampNs);
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 7676f59..ec3484c 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -236,9 +236,9 @@
void addActivation(int activationTrackerIndex, const ActivationType& activationType,
int64_t ttl_seconds, int deactivationTrackerIndex = -1);
- void prepareFistBucket() {
+ void prepareFirstBucket() {
std::lock_guard<std::mutex> lock(mMutex);
- prepareFistBucketLocked();
+ prepareFirstBucketLocked();
}
void flushIfExpire(int64_t elapsedTimestampNs);
@@ -272,7 +272,7 @@
void loadActiveMetricLocked(const ActiveMetric& activeMetric, int64_t currentTimeNs);
- virtual void prepareFistBucketLocked() {};
+ virtual void prepareFirstBucketLocked() {};
/**
* 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.
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 0bd6e62..17f2994 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -170,7 +170,7 @@
}
}
-void ValueMetricProducer::prepareFistBucketLocked() {
+void ValueMetricProducer::prepareFirstBucketLocked() {
// Kicks off the puller immediately if condition is true and diff based.
if (mIsActive && mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
pullAndMatchEventsLocked(mCurrentBucketStartTimeNs, mCondition);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 1821dea..de01e72 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -113,7 +113,7 @@
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
- void prepareFistBucketLocked() override;
+ void prepareFirstBucketLocked() override;
void dropDataLocked(const int64_t dropTimeNs) override;
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index b027fa0..dd32c08 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -766,9 +766,9 @@
return true;
}
-void prepareFistBucket(const vector<sp<MetricProducer>>& allMetricProducers) {
+void prepareFirstBucket(const vector<sp<MetricProducer>>& allMetricProducers) {
for (const auto& metric: allMetricProducers) {
- metric->prepareFistBucket();
+ metric->prepareFirstBucket();
}
}
@@ -829,7 +829,7 @@
return false;
}
- prepareFistBucket(allMetricProducers);
+ prepareFirstBucket(allMetricProducers);
return true;
}
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index 2a18e22..53dd5b7 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -92,10 +92,6 @@
// Returns the truncated timestamp.
int64_t truncateTimestampNsToFiveMinutes(int64_t timestampNs);
-inline bool isPushedAtom(int atomId) {
- return atomId <= util::kMaxPushedAtomId && atomId > 1;
-}
-
inline bool isVendorPulledAtom(int atomId) {
return atomId >= StatsdStats::kVendorPulledAtomStartTag && atomId < StatsdStats::kMaxAtomTag;
}
diff --git a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
index 8625487..bdc52b0 100644
--- a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
+++ b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
@@ -32,24 +32,32 @@
namespace statsd {
// clang-format off
-static const std::string DRIVER_PACKAGE_NAME = "TEST_DRIVER";
-static const std::string DRIVER_VERSION_NAME = "TEST_DRIVER_VERSION";
-static const std::string APP_PACKAGE_NAME = "TEST_APP";
-static const int64_t TIMESTAMP_WALLCLOCK = 111;
-static const int64_t TIMESTAMP_ELAPSED = 222;
-static const int64_t DRIVER_VERSION_CODE = 333;
-static const int64_t DRIVER_BUILD_TIME = 444;
-static const int64_t GL_LOADING_COUNT = 3;
-static const int64_t GL_LOADING_FAILURE_COUNT = 1;
-static const int64_t VK_LOADING_COUNT = 4;
-static const int64_t VK_LOADING_FAILURE_COUNT = 0;
-static const int64_t GL_DRIVER_LOADING_TIME_0 = 555;
-static const int64_t GL_DRIVER_LOADING_TIME_1 = 666;
-static const int64_t VK_DRIVER_LOADING_TIME_0 = 777;
-static const int64_t VK_DRIVER_LOADING_TIME_1 = 888;
-static const int64_t VK_DRIVER_LOADING_TIME_2 = 999;
-static const size_t NUMBER_OF_VALUES_GLOBAL = 8;
-static const size_t NUMBER_OF_VALUES_APP = 4;
+static const std::string DRIVER_PACKAGE_NAME = "TEST_DRIVER";
+static const std::string DRIVER_VERSION_NAME = "TEST_DRIVER_VERSION";
+static const std::string APP_PACKAGE_NAME = "TEST_APP";
+static const int64_t TIMESTAMP_WALLCLOCK = 111;
+static const int64_t TIMESTAMP_ELAPSED = 222;
+static const int64_t DRIVER_VERSION_CODE = 333;
+static const int64_t DRIVER_BUILD_TIME = 444;
+static const int64_t GL_LOADING_COUNT = 3;
+static const int64_t GL_LOADING_FAILURE_COUNT = 1;
+static const int64_t VK_LOADING_COUNT = 4;
+static const int64_t VK_LOADING_FAILURE_COUNT = 0;
+static const int64_t ANGLE_LOADING_COUNT = 2;
+static const int64_t ANGLE_LOADING_FAILURE_COUNT = 1;
+static const int64_t GL_DRIVER_LOADING_TIME_0 = 555;
+static const int64_t GL_DRIVER_LOADING_TIME_1 = 666;
+static const int64_t VK_DRIVER_LOADING_TIME_0 = 777;
+static const int64_t VK_DRIVER_LOADING_TIME_1 = 888;
+static const int64_t VK_DRIVER_LOADING_TIME_2 = 999;
+static const int64_t ANGLE_DRIVER_LOADING_TIME_0 = 1010;
+static const int64_t ANGLE_DRIVER_LOADING_TIME_1 = 1111;
+static const int32_t VULKAN_VERSION = 1;
+static const int32_t CPU_VULKAN_VERSION = 2;
+static const int32_t GLES_VERSION = 3;
+static const bool CPU_VULKAN_IN_USE = true;
+static const size_t NUMBER_OF_VALUES_GLOBAL = 13;
+static const size_t NUMBER_OF_VALUES_APP = 6;
// clang-format on
class MockGpuStatsPuller : public GpuStatsPuller {
@@ -93,6 +101,11 @@
EXPECT_TRUE(event->write(GL_LOADING_FAILURE_COUNT));
EXPECT_TRUE(event->write(VK_LOADING_COUNT));
EXPECT_TRUE(event->write(VK_LOADING_FAILURE_COUNT));
+ EXPECT_TRUE(event->write(VULKAN_VERSION));
+ EXPECT_TRUE(event->write(CPU_VULKAN_VERSION));
+ EXPECT_TRUE(event->write(GLES_VERSION));
+ EXPECT_TRUE(event->write(ANGLE_LOADING_COUNT));
+ EXPECT_TRUE(event->write(ANGLE_LOADING_FAILURE_COUNT));
event->init();
inData.emplace_back(event);
MockGpuStatsPuller mockPuller(android::util::GPU_STATS_GLOBAL_INFO, &inData);
@@ -110,6 +123,11 @@
EXPECT_EQ(GL_LOADING_FAILURE_COUNT, outData[0]->getValues()[5].mValue.long_value);
EXPECT_EQ(VK_LOADING_COUNT, outData[0]->getValues()[6].mValue.long_value);
EXPECT_EQ(VK_LOADING_FAILURE_COUNT, outData[0]->getValues()[7].mValue.long_value);
+ EXPECT_EQ(VULKAN_VERSION, outData[0]->getValues()[8].mValue.int_value);
+ EXPECT_EQ(CPU_VULKAN_VERSION, outData[0]->getValues()[9].mValue.int_value);
+ EXPECT_EQ(GLES_VERSION, outData[0]->getValues()[10].mValue.int_value);
+ EXPECT_EQ(ANGLE_LOADING_COUNT, outData[0]->getValues()[11].mValue.long_value);
+ EXPECT_EQ(ANGLE_LOADING_FAILURE_COUNT, outData[0]->getValues()[12].mValue.long_value);
}
TEST_F(GpuStatsPuller_test, PullGpuStatsAppInfo) {
@@ -125,8 +143,13 @@
vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_0);
vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_1);
vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_2);
+ std::vector<int64_t> angleDriverLoadingTime;
+ angleDriverLoadingTime.emplace_back(ANGLE_DRIVER_LOADING_TIME_0);
+ angleDriverLoadingTime.emplace_back(ANGLE_DRIVER_LOADING_TIME_1);
EXPECT_TRUE(event->write(int64VectorToProtoByteString(glDriverLoadingTime)));
EXPECT_TRUE(event->write(int64VectorToProtoByteString(vkDriverLoadingTime)));
+ EXPECT_TRUE(event->write(int64VectorToProtoByteString(angleDriverLoadingTime)));
+ EXPECT_TRUE(event->write(CPU_VULKAN_IN_USE));
event->init();
inData.emplace_back(event);
MockGpuStatsPuller mockPuller(android::util::GPU_STATS_APP_INFO, &inData);
@@ -142,6 +165,9 @@
outData[0]->getValues()[2].mValue.str_value);
EXPECT_EQ(int64VectorToProtoByteString(vkDriverLoadingTime),
outData[0]->getValues()[3].mValue.str_value);
+ EXPECT_EQ(int64VectorToProtoByteString(angleDriverLoadingTime),
+ outData[0]->getValues()[4].mValue.str_value);
+ EXPECT_EQ(CPU_VULKAN_IN_USE, outData[0]->getValues()[5].mValue.int_value);
}
} // namespace statsd
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 1ff7982..1b8a3b5 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -227,8 +227,6 @@
stats.noteAtomLogged(android::util::SENSOR_STATE_CHANGED, now + 1);
stats.noteAtomLogged(android::util::SENSOR_STATE_CHANGED, now + 2);
stats.noteAtomLogged(android::util::APP_CRASH_OCCURRED, now + 3);
- // pulled event, should ignore
- stats.noteAtomLogged(android::util::WIFI_BYTES_TRANSFER, now + 4);
vector<uint8_t> output;
stats.dumpStats(&output, false);
@@ -253,6 +251,39 @@
EXPECT_TRUE(sensorAtomGood);
}
+TEST(StatsdStatsTest, TestNonPlatformAtomLog) {
+ StatsdStats stats;
+ time_t now = time(nullptr);
+ int newAtom1 = android::util::kMaxPushedAtomId + 1;
+ int newAtom2 = android::util::kMaxPushedAtomId + 2;
+
+ stats.noteAtomLogged(newAtom1, now + 1);
+ stats.noteAtomLogged(newAtom1, now + 2);
+ stats.noteAtomLogged(newAtom2, now + 3);
+
+ vector<uint8_t> output;
+ stats.dumpStats(&output, false);
+ StatsdStatsReport report;
+ bool good = report.ParseFromArray(&output[0], output.size());
+ EXPECT_TRUE(good);
+
+ EXPECT_EQ(2, report.atom_stats_size());
+ bool newAtom1Good = false;
+ bool newAtom2Good = false;
+
+ for (const auto& atomStats : report.atom_stats()) {
+ if (atomStats.tag() == newAtom1 && atomStats.count() == 2) {
+ newAtom1Good = true;
+ }
+ if (atomStats.tag() == newAtom2 && atomStats.count() == 1) {
+ newAtom2Good = true;
+ }
+ }
+
+ EXPECT_TRUE(newAtom1Good);
+ EXPECT_TRUE(newAtom2Good);
+}
+
TEST(StatsdStatsTest, TestPullAtomStats) {
StatsdStats stats;
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index b9a5867..b9553a8 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -79,7 +79,7 @@
logEventMatcherIndex, eventMatcherWizard,
-1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2,
pullerManager);
- gaugeProducer.prepareFistBucket();
+ gaugeProducer.prepareFirstBucket();
EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs);
@@ -126,7 +126,7 @@
tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- gaugeProducer.prepareFistBucket();
+ gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -211,7 +211,7 @@
logEventMatcherIndex, eventMatcherWizard,
-1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- gaugeProducer.prepareFistBucket();
+ gaugeProducer.prepareFirstBucket();
sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
@@ -303,7 +303,7 @@
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- gaugeProducer.prepareFistBucket();
+ gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
@@ -370,7 +370,7 @@
logEventMatcherIndex, eventMatcherWizard,
tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- gaugeProducer.prepareFistBucket();
+ gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
@@ -431,7 +431,7 @@
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- gaugeProducer.prepareFistBucket();
+ gaugeProducer.prepareFirstBucket();
gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
@@ -529,7 +529,7 @@
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- gaugeProducer.prepareFistBucket();
+ gaugeProducer.prepareFirstBucket();
gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
@@ -583,7 +583,7 @@
logEventMatcherIndex, eventMatcherWizard,
tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- gaugeProducer.prepareFistBucket();
+ gaugeProducer.prepareFirstBucket();
Alert alert;
alert.set_id(101);
@@ -692,7 +692,7 @@
logEventMatcherIndex, eventMatcherWizard,
tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- gaugeProducer.prepareFistBucket();
+ gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -777,7 +777,7 @@
logEventMatcherIndex, eventMatcherWizard,
tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- gaugeProducer.prepareFistBucket();
+ gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 0e82bad..2262c76 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -105,7 +105,7 @@
kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- valueProducer->prepareFistBucket();
+ valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -125,7 +125,7 @@
new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer->prepareFistBucket();
+ valueProducer->prepareFirstBucket();
valueProducer->mCondition = ConditionState::kFalse;
return valueProducer;
}
@@ -169,7 +169,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
22, pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
@@ -199,7 +199,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1, 5,
600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
@@ -381,7 +381,7 @@
kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- valueProducer->prepareFistBucket();
+ valueProducer->prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -670,7 +670,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -728,7 +728,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -779,7 +779,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -854,7 +854,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -897,7 +897,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
@@ -972,7 +972,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
@@ -1269,7 +1269,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -1314,7 +1314,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -1361,7 +1361,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -1412,7 +1412,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -1458,7 +1458,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -1532,7 +1532,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -2081,7 +2081,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucket2StartTimeNs,
bucket2StartTimeNs, pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
// Event should be skipped since it is from previous bucket.
@@ -2862,7 +2862,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
ProtoOutputStream output;
std::set<string> strSet;
@@ -2905,7 +2905,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -2969,7 +2969,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.prepareFistBucket();
+ valueProducer.prepareFirstBucket();
ProtoOutputStream output;
std::set<string> strSet;
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 8c2b59d..09a8546 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -9193,13 +9193,6 @@
HSPLandroid/media/MediaMetadata$Builder;->build()Landroid/media/MediaMetadata;
HPLandroid/media/MediaMetadata;->size()I
HSPLandroid/media/MediaMetadata;->writeToParcel(Landroid/os/Parcel;I)V
-HSPLandroid/media/MediaParceledListSlice$2;-><init>()V
-HSPLandroid/media/MediaParceledListSlice$2;->createFromParcel(Landroid/os/Parcel;)Landroid/media/MediaParceledListSlice;
-HSPLandroid/media/MediaParceledListSlice$2;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
-HSPLandroid/media/MediaParceledListSlice;-><init>(Landroid/os/Parcel;)V
-HPLandroid/media/MediaParceledListSlice;-><init>(Ljava/util/List;)V
-HSPLandroid/media/MediaParceledListSlice;->getList()Ljava/util/List;
-HSPLandroid/media/MediaParceledListSlice;->writeToParcel(Landroid/os/Parcel;I)V
HSPLandroid/media/MediaPlayer$2$1;->getSubtitleLooper()Landroid/os/Looper;
HSPLandroid/media/MediaPlayer$2$1;->setSubtitleWidget(Landroid/media/SubtitleTrack$RenderingWidget;)V
HSPLandroid/media/MediaPlayer$2;->run()V
@@ -9446,7 +9439,7 @@
HPLandroid/media/session/ISessionControllerCallback$Stub$Proxy;->asBinder()Landroid/os/IBinder;
HPLandroid/media/session/ISessionControllerCallback$Stub$Proxy;->onMetadataChanged(Landroid/media/MediaMetadata;)V
HPLandroid/media/session/ISessionControllerCallback$Stub$Proxy;->onPlaybackStateChanged(Landroid/media/session/PlaybackState;)V
-HPLandroid/media/session/ISessionControllerCallback$Stub$Proxy;->onQueueChanged(Landroid/media/MediaParceledListSlice;)V
+HPLandroid/media/session/ISessionControllerCallback$Stub$Proxy;->onQueueChanged(Landroid/media/ParceledListSlice;)V
HPLandroid/media/session/ISessionControllerCallback$Stub$Proxy;->onSessionDestroyed()V
HSPLandroid/media/session/ISessionManager$Stub$Proxy;->getSessions(Landroid/content/ComponentName;I)Ljava/util/List;
HSPLandroid/media/session/ISessionManager$Stub;-><init>()V
diff --git a/config/hiddenapi-greylist-max-p.txt b/config/hiddenapi-greylist-max-p.txt
index 4c643e1..141e8e6 100644
--- a/config/hiddenapi-greylist-max-p.txt
+++ b/config/hiddenapi-greylist-max-p.txt
@@ -73,5 +73,5 @@
Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCallForwardingChanged(Z)V
Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCellLocation(Landroid/os/Bundle;)V
Lcom/android/internal/telephony/ITelephonyRegistry;->notifyDataActivity(I)V
-Lcom/android/internal/telephony/ITelephonyRegistry;->notifyOtaspChanged(I)V
+Lcom/android/internal/telephony/ITelephonyRegistry;->notifyOtaspChanged(II)V
Lcom/android/internal/view/BaseIWindow;-><init>()V
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 4abf924..c08ed26 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -126,7 +126,6 @@
import android.view.autofill.AutofillManager.AutofillClient;
import android.view.autofill.AutofillPopupWindow;
import android.view.autofill.IAutofillWindowPresenter;
-import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
import android.widget.AdapterView;
@@ -840,7 +839,7 @@
/** The autofill manager. Always access via {@link #getAutofillManager()}. */
@Nullable private AutofillManager mAutofillManager;
- /** The content capture manager. Always access via {@link #getContentCaptureManager()}. */
+ /** The content capture manager. Access via {@link #getContentCaptureManager()}. */
@Nullable private ContentCaptureManager mContentCaptureManager;
private final ArrayList<Application.ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
@@ -1092,12 +1091,11 @@
case CONTENT_CAPTURE_START:
//TODO(b/111276913): decide whether the InteractionSessionId should be
// saved / restored in the activity bundle - probably not
- int flags = 0;
- if ((getWindow().getAttributes().flags
- & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
- flags |= ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE;
+ final Window window = getWindow();
+ if (window != null) {
+ cm.updateWindowAttributes(window.getAttributes());
}
- cm.onActivityCreated(mToken, getComponentName(), flags);
+ cm.onActivityCreated(mToken, getComponentName());
break;
case CONTENT_CAPTURE_RESUME:
cm.onActivityResumed();
@@ -3668,7 +3666,25 @@
FragmentManager fragmentManager = mFragments.getFragmentManager();
- if (fragmentManager.isStateSaved() || !fragmentManager.popBackStackImmediate()) {
+ if (!fragmentManager.isStateSaved() && fragmentManager.popBackStackImmediate()) {
+ return;
+ }
+ if (!isTaskRoot()) {
+ // If the activity is not the root of the task, allow finish to proceed normally.
+ finishAfterTransition();
+ return;
+ }
+ try {
+ // Inform activity task manager that the activity received a back press
+ // while at the root of the task. This call allows ActivityTaskManager
+ // to intercept or defer finishing.
+ ActivityTaskManager.getService().onBackPressedOnTaskRoot(mToken,
+ new IRequestFinishCallback.Stub() {
+ public void requestFinish() {
+ finishAfterTransition();
+ }
+ });
+ } catch (RemoteException e) {
finishAfterTransition();
}
}
@@ -3785,6 +3801,9 @@
View decor = mDecor;
if (decor != null && decor.getParent() != null) {
getWindowManager().updateViewLayout(decor, params);
+ if (mContentCaptureManager != null) {
+ mContentCaptureManager.updateWindowAttributes(params);
+ }
}
}
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4b37461..ca04536a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1069,7 +1069,7 @@
}
public void scheduleApplicationInfoChanged(ApplicationInfo ai) {
- mH.removeMessages(H.APPLICATION_INFO_CHANGED);
+ mH.removeMessages(H.APPLICATION_INFO_CHANGED, ai);
sendMessage(H.APPLICATION_INFO_CHANGED, ai);
}
@@ -3393,6 +3393,9 @@
}
WindowManagerGlobal.initialize();
+ // Hint the GraphicsEnvironment that an activity is launching on the process.
+ GraphicsEnvironment.hintActivityLaunch();
+
final Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index fc6fffa..864af8c 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -28,6 +28,7 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Insets;
+import android.graphics.Matrix;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
@@ -51,6 +52,7 @@
import android.view.ViewParent;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.inputmethod.InputMethodManager;
import dalvik.system.CloseGuard;
@@ -317,7 +319,15 @@
* regions and avoid focus switches by touches on this view.
*/
public void onLocationChanged() {
- updateTapExcludeRegion();
+ updateLocationAndTapExcludeRegion();
+ }
+
+ private void clearActivityViewGeometryForIme() {
+ if (mVirtualDisplay == null) {
+ return;
+ }
+ final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
+ mContext.getSystemService(InputMethodManager.class).reportActivityView(displayId, null);
}
@Override
@@ -329,37 +339,59 @@
public boolean gatherTransparentRegion(Region region) {
// The tap exclude region may be affected by any view on top of it, so we detect the
// possible change by monitoring this function.
- updateTapExcludeRegion();
+ updateLocationAndTapExcludeRegion();
return super.gatherTransparentRegion(region);
}
- /** Compute and send current tap exclude region to WM for this view. */
- private void updateTapExcludeRegion() {
- if (!isAttachedToWindow()) {
+ /**
+ * Sends current location in window and tap exclude region to WM for this view.
+ */
+ private void updateLocationAndTapExcludeRegion() {
+ if (mVirtualDisplay == null || !isAttachedToWindow()) {
return;
}
+ try {
+ int x = mLocationInWindow[0];
+ int y = mLocationInWindow[1];
+ getLocationInWindow(mLocationInWindow);
+ if (x != mLocationInWindow[0] || y != mLocationInWindow[1]) {
+ x = mLocationInWindow[0];
+ y = mLocationInWindow[1];
+ final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
+ WindowManagerGlobal.getWindowSession().updateDisplayContentLocation(
+ getWindow(), x, y, displayId);
+
+ // Also report this geometry information to InputMethodManagerService.
+ // TODO(b/115693908): Unify this logic into the above WMS-based one.
+ final Matrix matrix = new Matrix();
+ matrix.set(getMatrix());
+ matrix.postTranslate(x, y);
+ mContext.getSystemService(InputMethodManager.class)
+ .reportActivityView(displayId, matrix);
+ }
+ updateTapExcludeRegion(x, y);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /** Computes and sends current tap exclude region to WM for this view. */
+ private void updateTapExcludeRegion(int x, int y) throws RemoteException {
if (!canReceivePointerEvents()) {
cleanTapExcludeRegion();
return;
}
- try {
- getLocationInWindow(mLocationInWindow);
- final int x = mLocationInWindow[0];
- final int y = mLocationInWindow[1];
- mTapExcludeRegion.set(x, y, x + getWidth(), y + getHeight());
+ mTapExcludeRegion.set(x, y, x + getWidth(), y + getHeight());
- // There might be views on top of us. We need to subtract those areas from the tap
- // exclude region.
- final ViewParent parent = getParent();
- if (parent instanceof ViewGroup) {
- ((ViewGroup) parent).subtractObscuredTouchableRegion(mTapExcludeRegion, this);
- }
-
- WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
- mTapExcludeRegion);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
+ // There might be views on top of us. We need to subtract those areas from the tap
+ // exclude region.
+ final ViewParent parent = getParent();
+ if (parent != null) {
+ parent.subtractObscuredTouchableRegion(mTapExcludeRegion, this);
}
+
+ WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
+ mTapExcludeRegion);
}
private class SurfaceCallback implements SurfaceHolder.Callback {
@@ -379,7 +411,7 @@
mVirtualDisplay.setDisplayState(true);
}
- updateTapExcludeRegion();
+ updateLocationAndTapExcludeRegion();
}
@Override
@@ -387,7 +419,7 @@
if (mVirtualDisplay != null) {
mVirtualDisplay.resize(width, height, getBaseDisplayDensity());
}
- updateTapExcludeRegion();
+ updateLocationAndTapExcludeRegion();
}
@Override
@@ -395,6 +427,7 @@
if (mVirtualDisplay != null) {
mVirtualDisplay.setDisplayState(false);
}
+ clearActivityViewGeometryForIme();
cleanTapExcludeRegion();
}
}
@@ -471,7 +504,8 @@
try {
// TODO: Find a way to consolidate these calls to the server.
- wm.reparentDisplayContent(displayId, mRootSurfaceControl);
+ WindowManagerGlobal.getWindowSession().reparentDisplayContent(
+ getWindow(), mRootSurfaceControl, displayId);
wm.dontOverrideDisplayInfo(displayId);
if (mSingleTaskInstance) {
mActivityTaskManager.setDisplayToSingleTaskInstance(displayId);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 713fd1c..f8d7b51 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -3119,6 +3119,15 @@
return mHistoricalUidOps.get(uid);
}
+ /** @hide */
+ public void clearHistory(int uid, @NonNull String packageName) {
+ HistoricalUidOps historicalUidOps = getOrCreateHistoricalUidOps(uid);
+ historicalUidOps.clearHistory(packageName);
+ if (historicalUidOps.isEmpty()) {
+ mHistoricalUidOps.remove(uid);
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -3396,6 +3405,12 @@
return mHistoricalPackageOps.get(packageName);
}
+ private void clearHistory(@NonNull String packageName) {
+ if (mHistoricalPackageOps != null) {
+ mHistoricalPackageOps.remove(packageName);
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -4294,6 +4309,12 @@
/**
* Retrieve current operation state for all applications.
*
+ * The mode of the ops returned are set for the package but may not reflect their effective
+ * state due to UID policy or because it's controlled by a different master op.
+ *
+ * Use {@link #unsafeCheckOp(String, int, String)}} or {@link #noteOp(String, int, String)}
+ * if the effective mode is needed.
+ *
* @param ops The set of operations you are interested in, or null if you want all of them.
* @hide
*/
@@ -4312,6 +4333,12 @@
/**
* Retrieve current operation state for all applications.
*
+ * The mode of the ops returned are set for the package but may not reflect their effective
+ * state due to UID policy or because it's controlled by a different master op.
+ *
+ * Use {@link #unsafeCheckOp(String, int, String)}} or {@link #noteOp(String, int, String)}
+ * if the effective mode is needed.
+ *
* @param ops The set of operations you are interested in, or null if you want all of them.
* @hide
*/
@@ -4328,6 +4355,12 @@
/**
* Retrieve current operation state for one application.
*
+ * The mode of the ops returned are set for the package but may not reflect their effective
+ * state due to UID policy or because it's controlled by a different master op.
+ *
+ * Use {@link #unsafeCheckOp(String, int, String)}} or {@link #noteOp(String, int, String)}
+ * if the effective mode is needed.
+ *
* @param uid The uid of the application of interest.
* @param packageName The name of the application of interest.
* @param ops The set of operations you are interested in, or null if you want all of them.
@@ -4354,6 +4387,12 @@
* Retrieve current operation state for one application. The UID and the
* package must match.
*
+ * The mode of the ops returned are set for the package but may not reflect their effective
+ * state due to UID policy or because it's controlled by a different master op.
+ *
+ * Use {@link #unsafeCheckOp(String, int, String)}} or {@link #noteOp(String, int, String)}
+ * if the effective mode is needed.
+ *
* @param uid The uid of the application of interest.
* @param packageName The name of the application of interest.
* @param ops The set of operations you are interested in, or null if you want all of them.
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 82a34ce..4e22cc1 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2751,7 +2751,8 @@
/**
* @hide
*/
- public Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
+ public Drawable loadUnbadgedItemIcon(@NonNull PackageItemInfo itemInfo,
+ @Nullable ApplicationInfo appInfo) {
if (itemInfo.showUserIcon != UserHandle.USER_NULL) {
Bitmap bitmap = getUserManager().getUserIcon(itemInfo.showUserIcon);
if (bitmap == null) {
@@ -2764,6 +2765,9 @@
if (itemInfo.packageName != null) {
dr = getDrawable(itemInfo.packageName, itemInfo.icon, appInfo);
}
+ if (dr == null && itemInfo != appInfo && appInfo != null) {
+ dr = loadUnbadgedItemIcon(appInfo, appInfo);
+ }
if (dr == null) {
dr = itemInfo.loadDefaultIcon(this);
}
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index be281c2..584115a 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -539,8 +539,9 @@
*
* <p> For applications targeting {@link android.os.Build.VERSION_CODES#Q} or above,
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE}
- * permission is not needed and the {@code dirType} must
- * be {@link Environment#DIRECTORY_DOWNLOADS}.
+ * permission is not needed and the {@code dirType} must be one of the known public
+ * directories like {@link Environment#DIRECTORY_DOWNLOADS},
+ * {@link Environment#DIRECTORY_PICTURES}, {@link Environment#DIRECTORY_MOVIES}, etc.
*
* @param dirType the directory type to pass to {@link Environment#getExternalStoragePublicDirectory(String)}
* @param subPath the path within the external directory, including the
@@ -594,11 +595,8 @@
* should be called before {@link DownloadManager#enqueue(Request)} is called.
*
* @deprecated Starting in Q, this value is ignored. Files downloaded to
- * public Downloads directory (as returned by
- * {@link Environment#getExternalStoragePublicDirectory(String)} with
- * {@link Environment#DIRECTORY_DOWNLOADS}) will be scanned by MediaScanner
- * and files downloaded to directories owned by applications
- * (e.g. {@link Context#getExternalFilesDir(String)}) will not be scanned.
+ * directories owned by applications (e.g. {@link Context#getExternalFilesDir(String)})
+ * will not be scanned by MediaScanner and the rest will be scanned.
*/
@Deprecated
public void allowScanningByMediaScanner() {
@@ -783,11 +781,11 @@
* @param isVisible whether to display this download in the Downloads UI
* @return this object
*
- * @deprecated Starting in Q, this value is ignored. Files downloaded to
+ * @deprecated Starting in Q, this value is ignored. Only files downloaded to
* public Downloads directory (as returned by
* {@link Environment#getExternalStoragePublicDirectory(String)} with
* {@link Environment#DIRECTORY_DOWNLOADS}) will be visible in system's Downloads UI
- * and files downloaded to directories owned by applications
+ * and the rest will not be visible.
* (e.g. {@link Context#getExternalFilesDir(String)}) will not be visible.
*/
@Deprecated
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 7953d42..26720fc 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -26,6 +26,7 @@
import android.app.IAssistDataReceiver;
import android.app.IInstrumentationWatcher;
import android.app.IProcessObserver;
+import android.app.IRequestFinishCallback;
import android.app.IServiceConnection;
import android.app.IStopUserCallback;
import android.app.ITaskStackListener;
@@ -484,4 +485,12 @@
* @param activityToken The token of the target activity to restart.
*/
void restartActivityProcessIfVisible(in IBinder activityToken);
+
+ /**
+ * Reports that an Activity received a back key press when there were no additional activities
+ * on the back stack. If the Activity should be finished, the callback will be invoked. A
+ * callback is used instead of finishing the activity directly from the server such that the
+ * client may perform actions prior to finishing.
+ */
+ void onBackPressedOnTaskRoot(in IBinder activityToken, in IRequestFinishCallback callback);
}
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index b3c2429..e57738f 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -102,7 +102,6 @@
NotificationChannelGroup getNotificationChannelGroup(String pkg, String channelGroupId);
ParceledListSlice getNotificationChannelGroups(String pkg);
boolean onlyHasDefaultChannel(String pkg, int uid);
- ParceledListSlice getRecentNotifyingAppsForUser(int userId);
int getBlockedAppCount(int userId);
boolean areChannelsBypassingDnd();
int getAppsBypassingDndCount(int uid);
diff --git a/cmds/incidentd/src/cipher/cipher_blocks.proto b/core/java/android/app/IRequestFinishCallback.aidl
similarity index 71%
copy from cmds/incidentd/src/cipher/cipher_blocks.proto
copy to core/java/android/app/IRequestFinishCallback.aidl
index 5c7ed24..3270565 100644
--- a/cmds/incidentd/src/cipher/cipher_blocks.proto
+++ b/core/java/android/app/IRequestFinishCallback.aidl
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-syntax = "proto2";
+package android.app;
-package android.os.incidentd;
-
-// This proto is never instantiated anywhere. It only exists to keep a record of the format of the
-// encrypted data on disk.
-message CipherBlocks {
- repeated string blocks = 1;
+/**
+ * This callback allows ActivityTaskManager to ask the calling Activity
+ * to finish in response to a call to onBackPressedOnTaskRoot.
+ *
+ * {@hide}
+ */
+oneway interface IRequestFinishCallback {
+ void requestFinish();
}
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 841ff6a..1fdc8ca5 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -161,4 +161,12 @@
* @see com.android.server.wm.AppWindowToken#inSizeCompatMode
*/
void onSizeCompatModeActivityChanged(int displayId, in IBinder activityToken);
+
+ /**
+ * Reports that an Activity received a back key press when there were no additional activities
+ * on the back stack.
+ *
+ * @param taskInfo info about the task which received the back press
+ */
+ void onBackPressedOnTaskRoot(in ActivityManager.RunningTaskInfo taskInfo);
}
diff --git a/core/java/android/app/JobSchedulerImpl.java b/core/java/android/app/JobSchedulerImpl.java
index 5494e2a..e877018 100644
--- a/core/java/android/app/JobSchedulerImpl.java
+++ b/core/java/android/app/JobSchedulerImpl.java
@@ -83,7 +83,7 @@
@Override
public List<JobInfo> getAllPendingJobs() {
try {
- return mBinder.getAllPendingJobs();
+ return mBinder.getAllPendingJobs().getList();
} catch (RemoteException e) {
return null;
}
@@ -110,7 +110,7 @@
@Override
public List<JobSnapshot> getAllJobSnapshots() {
try {
- return mBinder.getAllJobSnapshots();
+ return mBinder.getAllJobSnapshots().getList();
} catch (RemoteException e) {
return null;
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 310cce4..1ac619c 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1497,7 +1497,7 @@
private Intent mCurIntent;
private final boolean mOrdered;
private boolean mDispatched;
- private Throwable mPreviousRunStacktrace; // To investigate b/37809561. STOPSHIP remove.
+ private boolean mRunCalled;
public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
boolean ordered, boolean sticky, int sendingUser) {
@@ -1525,13 +1525,12 @@
final Intent intent = mCurIntent;
if (intent == null) {
Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
- + ": run() previously called at "
- + Log.getStackTraceString(mPreviousRunStacktrace));
+ + (mRunCalled ? ", run() has already been called" : ""));
}
mCurIntent = null;
mDispatched = true;
- mPreviousRunStacktrace = new Throwable("Previous stacktrace");
+ mRunCalled = true;
if (receiver == null || intent == null || mForgotten) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 15b571f..789351e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -618,11 +618,13 @@
public static final int FLAG_CAN_COLORIZE = 0x00000800;
/**
- * Bit to be bitswised-ored into the {@link #flags} field that should be set if this
- * notification is showing as a bubble. This will be set by the system if it is determined
- * that your notification is allowed to be a bubble.
+ * Bit to be bitswised-ored into the {@link #flags} field that should be
+ * set by the system if this notification is showing as a bubble.
*
- * @see {@link Notification.Builder#setBubbleMetadata(BubbleMetadata)}
+ * Applications cannot set this flag directly; they should instead call
+ * {@link Notification.Builder#setBubbleMetadata(BubbleMetadata)} to
+ * request that a notification be displayed as a bubble, and then check
+ * this flag to see whether that request was honored by the system.
*/
public static final int FLAG_BUBBLE = 0x00001000;
@@ -4884,7 +4886,8 @@
R.id.progress, ColorStateList.valueOf(mContext.getColor(
R.color.notification_progress_background_color)));
if (getRawColor(p) != COLOR_DEFAULT) {
- ColorStateList colorStateList = ColorStateList.valueOf(resolveContrastColor(p));
+ int color = isColorized(p) ? getPrimaryTextColor(p) : resolveContrastColor(p);
+ ColorStateList colorStateList = ColorStateList.valueOf(color);
contentView.setProgressTintList(R.id.progress, colorStateList);
contentView.setProgressIndeterminateTintList(R.id.progress, colorStateList);
}
@@ -6253,7 +6256,7 @@
}
/**
- * @return true if this is a notification that can show as a bubble.
+ * @return true if this notification is showing as a bubble
*
* @hide
*/
@@ -8707,6 +8710,10 @@
/**
* Sets the intent that will be used when the bubble is expanded. This will display the
* app content in a floating window over the existing foreground activity.
+ *
+ * <p>An intent is required.</p>
+ *
+ * @throws IllegalArgumentException if intent is null
*/
@NonNull
public BubbleMetadata.Builder setIntent(@NonNull PendingIntent intent) {
@@ -8731,6 +8738,8 @@
*
* If your icon is not bitmap-based, you should expect that the icon will be tinted.
* </p>
+ *
+ * @throws IllegalArgumentException if icon is null or a non-adaptive bitmap
*/
@NonNull
public BubbleMetadata.Builder setIcon(@NonNull Icon icon) {
@@ -8748,12 +8757,18 @@
/**
* Sets the desired height in DPs for the app content defined by
- * {@link #setIntent(PendingIntent)}, this height may not be respected if there is not
- * enough space on the screen or if the provided height is too small to be useful.
- * <p>
- * If {@link #setDesiredHeightResId(int)} was previously called on this builder, the
+ * {@link #setIntent(PendingIntent)}.
+ *
+ * <p>This height may not be respected if there is not enough space on the screen or if
+ * the provided height is too small to be useful.</p>
+ *
+ * <p>If {@link #setDesiredHeightResId(int)} was previously called on this builder, the
* previous value set will be cleared after calling this method, and this value will
- * be used instead.
+ * be used instead.</p>
+ *
+ * <p>A desired height (in DPs or via resID) is optional.</p>
+ *
+ * @see #setDesiredHeightResId(int)
*/
@NonNull
public BubbleMetadata.Builder setDesiredHeight(@Dimension(unit = DP) int height) {
@@ -8765,12 +8780,18 @@
/**
* Sets the desired height via resId for the app content defined by
- * {@link #setIntent(PendingIntent)}, this height may not be respected if there is not
- * enough space on the screen or if the provided height is too small to be useful.
- * <p>
- * If {@link #setDesiredHeight(int)} was previously called on this builder, the
+ * {@link #setIntent(PendingIntent)}.
+ *
+ * <p>This height may not be respected if there is not enough space on the screen or if
+ * the provided height is too small to be useful.</p>
+ *
+ * <p>If {@link #setDesiredHeight(int)} was previously called on this builder, the
* previous value set will be cleared after calling this method, and this value will
- * be used instead.
+ * be used instead.</p>
+ *
+ * <p>A desired height (in DPs or via resID) is optional.</p>
+ *
+ * @see #setDesiredHeight(int)
*/
@NonNull
public BubbleMetadata.Builder setDesiredHeightResId(@DimenRes int heightResId) {
@@ -8780,15 +8801,16 @@
}
/**
- * If set and the app creating the bubble is in the foreground, the bubble will be
- * posted in its expanded state, with the contents of {@link #getIntent()} in a
- * floating window.
+ * Sets whether the bubble will be posted in its expanded state (with the contents of
+ * {@link #getIntent()} in a floating window).
*
- * <p>If the app creating the bubble is not in the foreground this flag has no effect.
+ * <p>This flag has no effect if the app posting the bubble is not in the foreground.
* </p>
*
- * <p>Generally this flag should only be set if the user has performed an action to
+ * <p>Generally, this flag should only be set if the user has performed an action to
* request or create a bubble.</p>
+ *
+ * <p>Setting this flag is optional; it defaults to false.</p>
*/
@NonNull
public BubbleMetadata.Builder setAutoExpandBubble(boolean shouldExpand) {
@@ -8797,24 +8819,28 @@
}
/**
- * If set and the app posting the bubble is in the foreground, the bubble will be
- * posted <b>without</b> the associated notification in the notification shade.
+ * Sets whether the bubble will be posted <b>without</b> the associated notification in
+ * the notification shade.
*
- * <p>If the app posting the bubble is not in the foreground this flag has no effect.
+ * <p>This flag has no effect if the app posting the bubble is not in the foreground.
* </p>
*
- * <p>Generally this flag should only be set if the user has performed an action to
+ * <p>Generally, this flag should only be set if the user has performed an action to
* request or create a bubble, or if the user has seen the content in the notification
* and the notification is no longer relevant.</p>
+ *
+ * <p>Setting this flag is optional; it defaults to false.</p>
*/
@NonNull
- public BubbleMetadata.Builder setSuppressNotification(boolean shouldSupressNotif) {
- setFlag(FLAG_SUPPRESS_NOTIFICATION, shouldSupressNotif);
+ public BubbleMetadata.Builder setSuppressNotification(boolean shouldSuppressNotif) {
+ setFlag(FLAG_SUPPRESS_NOTIFICATION, shouldSuppressNotif);
return this;
}
/**
- * Sets an optional intent to send when this bubble is explicitly removed by the user.
+ * Sets an intent to send when this bubble is explicitly removed by the user.
+ *
+ * <p>Setting a delete intent is optional.</p>
*/
@NonNull
public BubbleMetadata.Builder setDeleteIntent(@Nullable PendingIntent deleteIntent) {
@@ -8824,8 +8850,10 @@
/**
* Creates the {@link BubbleMetadata} defined by this builder.
- * <p>Will throw {@link IllegalStateException} if required fields have not been set
- * on this builder.</p>
+ *
+ * @throws IllegalStateException if {@link #setIntent(PendingIntent)} and/or
+ * {@link #setIcon(Icon)} have not been called on this
+ * builder.
*/
@NonNull
public BubbleMetadata build() {
diff --git a/core/java/android/app/SharedElementCallback.java b/core/java/android/app/SharedElementCallback.java
index 9fabfde..0287564 100644
--- a/core/java/android/app/SharedElementCallback.java
+++ b/core/java/android/app/SharedElementCallback.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.RectF;
@@ -49,6 +50,7 @@
private static final String BUNDLE_SNAPSHOT_BITMAP = "sharedElement:snapshot:bitmap";
private static final String BUNDLE_SNAPSHOT_GRAPHIC_BUFFER =
"sharedElement:snapshot:graphicBuffer";
+ private static final String BUNDLE_SNAPSHOT_COLOR_SPACE = "sharedElement:snapshot:colorSpace";
private static final String BUNDLE_SNAPSHOT_IMAGE_SCALETYPE = "sharedElement:snapshot:imageScaleType";
private static final String BUNDLE_SNAPSHOT_IMAGE_MATRIX = "sharedElement:snapshot:imageMatrix";
@@ -186,6 +188,10 @@
} else {
GraphicBuffer graphicBuffer = bitmap.createGraphicBufferHandle();
bundle.putParcelable(BUNDLE_SNAPSHOT_GRAPHIC_BUFFER, graphicBuffer);
+ ColorSpace cs = bitmap.getColorSpace();
+ if (cs != null) {
+ bundle.putInt(BUNDLE_SNAPSHOT_COLOR_SPACE, cs.getId());
+ }
}
bundle.putString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE,
imageView.getScaleType().toString());
@@ -235,8 +241,13 @@
return null;
}
if (bitmap == null) {
+ ColorSpace colorSpace = null;
+ int colorSpaceId = bundle.getInt(BUNDLE_SNAPSHOT_COLOR_SPACE, 0);
+ if (colorSpaceId >= 0 && colorSpaceId < ColorSpace.Named.values().length) {
+ colorSpace = ColorSpace.get(ColorSpace.Named.values()[colorSpaceId]);
+ }
bitmap = Bitmap.wrapHardwareBuffer(HardwareBuffer.createFromGraphicBuffer(buffer),
- null);
+ colorSpace);
}
ImageView imageView = new ImageView(context);
view = imageView;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index c48c878..d32b6b5 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -618,7 +618,7 @@
new CachedServiceFetcher<RcsManager>() {
@Override
public RcsManager createService(ContextImpl ctx) {
- return new RcsManager();
+ return new RcsManager(ctx.getOuterContext());
}
});
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 97b9176..00f3ad5 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -19,6 +19,7 @@
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager.TaskSnapshot;
import android.content.ComponentName;
+import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -155,6 +156,11 @@
@Override
@UnsupportedAppUsage
public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) throws RemoteException {
+ if (Binder.getCallingPid() != android.os.Process.myPid()
+ && snapshot != null && snapshot.getSnapshot() != null) {
+ // Preemptively clear any reference to the buffer
+ snapshot.getSnapshot().destroy();
+ }
}
@Override
@@ -162,4 +168,9 @@
public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken)
throws RemoteException {
}
+
+ @Override
+ public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ }
}
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index 7828573..b37120f 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -79,10 +79,10 @@
/** @hide */
public static final String KEY_KILL_SIGNAL = "key_kill_signal";
- IVoiceInteractor mInteractor;
+ @Nullable IVoiceInteractor mInteractor;
- Context mContext;
- Activity mActivity;
+ @Nullable Context mContext;
+ @Nullable Activity mActivity;
boolean mRetaining;
final HandlerCaller mHandlerCaller;
@@ -999,7 +999,9 @@
// destroyed now
mInteractor = null;
- mActivity.setVoiceInteractor(null);
+ if (mActivity != null) {
+ mActivity.setVoiceInteractor(null);
+ }
}
public boolean submitRequest(Request request) {
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 0d5a763..3fca311 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -699,6 +699,7 @@
static final int AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS = 0x100;
static final int AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS = 0x200;
static final int AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH = 0x400;
+ static final int AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID = 0x800;
int mFlags;
int mAutofillFlags;
@@ -754,6 +755,9 @@
} else {
mAutofillId = new AutofillId(autofillViewId);
}
+ if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID) != 0) {
+ mAutofillId.setSessionId(in.readInt());
+ }
}
if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE) != 0) {
mAutofillType = in.readInt();
@@ -899,6 +903,9 @@
if (mAutofillId.isVirtualInt()) {
autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID;
}
+ if (mAutofillId.hasSession()) {
+ autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID;
+ }
}
if (mAutofillValue != null) {
autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE;
@@ -965,7 +972,9 @@
if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID) != 0) {
out.writeInt(mAutofillId.getVirtualChildIntId());
}
- // TODO(b/113593220): write session id as well
+ if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID) != 0) {
+ out.writeInt(mAutofillId.getSessionId());
+ }
}
if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE) != 0) {
out.writeInt(mAutofillType);
diff --git a/core/java/android/app/job/IJobScheduler.aidl b/core/java/android/app/job/IJobScheduler.aidl
index 53b33c2..3006f50 100644
--- a/core/java/android/app/job/IJobScheduler.aidl
+++ b/core/java/android/app/job/IJobScheduler.aidl
@@ -19,6 +19,7 @@
import android.app.job.JobInfo;
import android.app.job.JobSnapshot;
import android.app.job.JobWorkItem;
+import android.content.pm.ParceledListSlice;
/**
* IPC interface that supports the app-facing {@link #JobScheduler} api.
@@ -30,8 +31,8 @@
int scheduleAsPackage(in JobInfo job, String packageName, int userId, String tag);
void cancel(int jobId);
void cancelAll();
- List<JobInfo> getAllPendingJobs();
+ ParceledListSlice getAllPendingJobs();
JobInfo getPendingJob(int jobId);
List<JobInfo> getStartedJobs();
- List<JobSnapshot> getAllJobSnapshots();
+ ParceledListSlice getAllJobSnapshots();
}
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 59ae334..8e40449 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -278,6 +278,12 @@
return null;
}
+ return querySummary(template, startTime, endTime);
+ }
+
+ /** @hide */
+ public NetworkStats querySummary(NetworkTemplate template, long startTime,
+ long endTime) throws SecurityException, RemoteException {
NetworkStats result;
result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
result.startSummaryEnumeration();
@@ -296,6 +302,13 @@
NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
}
+ /** @hide */
+ public NetworkStats queryDetailsForUid(NetworkTemplate template,
+ long startTime, long endTime, int uid) throws SecurityException {
+ return queryDetailsForUidTagState(template, startTime, endTime, uid,
+ NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
+ }
+
/**
* Query network usage statistics details for a given uid and tag.
*
@@ -340,6 +353,13 @@
NetworkTemplate template;
template = createTemplate(networkType, subscriberId);
+ return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
+ }
+
+ /** @hide */
+ public NetworkStats queryDetailsForUidTagState(NetworkTemplate template,
+ long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
+
NetworkStats result;
try {
result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 442b239..1fe1b10 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -22,23 +22,16 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.ParcelUuid;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
-import com.android.internal.annotations.GuardedBy;
-
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
@@ -209,101 +202,32 @@
@UnsupportedAppUsage
public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
- private Context mContext;
- private ServiceListener mServiceListener;
- private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
- @GuardedBy("mServiceLock")
- private IBluetoothA2dp mService;
private BluetoothAdapter mAdapter;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- try {
- mServiceLock.writeLock().lock();
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.writeLock().unlock();
- }
- } else {
- try {
- mServiceLock.readLock().lock();
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.readLock().unlock();
- }
- }
+ private final BluetoothProfileConnector<IBluetoothA2dp> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.A2DP, "BluetoothA2dp",
+ IBluetoothA2dp.class.getName()) {
+ @Override
+ public IBluetoothA2dp getServiceInterface(IBinder service) {
+ return IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothA2dp proxy object for interacting with the local
* Bluetooth A2DP service.
*/
- /*package*/ BluetoothA2dp(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothA2dp(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothA2dp.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
@UnsupportedAppUsage
/*package*/ void close() {
- mServiceListener = null;
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- try {
- mServiceLock.writeLock().lock();
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.writeLock().unlock();
- }
+ private IBluetoothA2dp getService() {
+ return mProfileConnector.getService();
}
@Override
@@ -333,17 +257,15 @@
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.connect(device);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.connect(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -376,17 +298,15 @@
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.disconnect(device);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.disconnect(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -397,17 +317,15 @@
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getConnectedDevices();
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ return service.getConnectedDevices();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -418,17 +336,15 @@
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getDevicesMatchingConnectionStates(states);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ return service.getDevicesMatchingConnectionStates(states);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -439,18 +355,16 @@
public @BtProfileState int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -480,18 +394,16 @@
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& ((device == null) || isValidDevice(device))) {
- return mService.setActiveDevice(device);
+ return service.setActiveDevice(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -511,17 +423,15 @@
public BluetoothDevice getActiveDevice() {
if (VDBG) log("getActiveDevice()");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getActiveDevice();
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ return service.getActiveDevice();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return null;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return null;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -543,22 +453,20 @@
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -578,18 +486,16 @@
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getPriority(device);
+ return service.getPriority(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.PRIORITY_OFF;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.PRIORITY_OFF;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -602,17 +508,15 @@
public boolean isAvrcpAbsoluteVolumeSupported() {
if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.isAvrcpAbsoluteVolumeSupported();
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ return service.isAvrcpAbsoluteVolumeSupported();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -625,15 +529,13 @@
public void setAvrcpAbsoluteVolume(int volume) {
if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- mService.setAvrcpAbsoluteVolume(volume);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ service.setAvrcpAbsoluteVolume(volume);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -646,18 +548,16 @@
*/
public boolean isA2dpPlaying(BluetoothDevice device) {
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.isA2dpPlaying(device);
+ return service.isA2dpPlaying(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -694,19 +594,17 @@
public @Nullable BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getCodecStatus(device);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ return service.getCodecStatus(device);
}
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
return null;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in getCodecStatus()", e);
return null;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -723,17 +621,15 @@
BluetoothCodecConfig codecConfig) {
if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- mService.setCodecConfigPreference(device, codecConfig);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ service.setCodecConfigPreference(device, codecConfig);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e);
return;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -772,21 +668,19 @@
*/
private void enableDisableOptionalCodecs(BluetoothDevice device, boolean enable) {
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
if (enable) {
- mService.enableOptionalCodecs(device);
+ service.enableOptionalCodecs(device);
} else {
- mService.disableOptionalCodecs(device);
+ service.disableOptionalCodecs(device);
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in enableDisableOptionalCodecs()", e);
return;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -801,17 +695,15 @@
@UnsupportedAppUsage
public int supportsOptionalCodecs(BluetoothDevice device) {
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.supportsOptionalCodecs(device);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.supportsOptionalCodecs(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -826,17 +718,15 @@
@UnsupportedAppUsage
public int getOptionalCodecsEnabled(BluetoothDevice device) {
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.getOptionalCodecsEnabled(device);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.getOptionalCodecsEnabled(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_PREF_UNKNOWN;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
return OPTIONAL_CODECS_PREF_UNKNOWN;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -858,18 +748,16 @@
Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value);
return;
}
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- mService.setOptionalCodecsEnabled(device, value);
+ service.setOptionalCodecsEnabled(device, value);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -900,35 +788,6 @@
}
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- try {
- mServiceLock.writeLock().lock();
- mService = IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
- } finally {
- mServiceLock.writeLock().unlock();
- }
-
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- try {
- mServiceLock.writeLock().lock();
- mService = null;
- } finally {
- mServiceLock.writeLock().unlock();
- }
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
- }
- }
- };
-
private boolean isEnabled() {
if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
return false;
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index cb996f3..5a8055a 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -17,14 +17,10 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -125,93 +121,31 @@
public static final String EXTRA_AUDIO_CONFIG =
"android.bluetooth.a2dp-sink.profile.extra.AUDIO_CONFIG";
- private Context mContext;
- private ServiceListener mServiceListener;
- private volatile IBluetoothA2dpSink mService;
private BluetoothAdapter mAdapter;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private final BluetoothProfileConnector<IBluetoothA2dpSink> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.A2DP_SINK,
+ "BluetoothA2dpSink", IBluetoothA2dpSink.class.getName()) {
+ @Override
+ public IBluetoothA2dpSink getServiceInterface(IBinder service) {
+ return IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothA2dp proxy object for interacting with the local
* Bluetooth A2DP service.
*/
- /*package*/ BluetoothA2dpSink(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothA2dpSink(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothA2dpSink.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
- mServiceListener = null;
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private IBluetoothA2dpSink getService() {
+ return mProfileConnector.getService();
}
@Override
@@ -242,7 +176,7 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -283,7 +217,7 @@
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -302,7 +236,7 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -321,7 +255,7 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -340,7 +274,7 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -366,7 +300,7 @@
*/
public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
if (VDBG) log("getAudioConfig(" + device + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getAudioConfig(device);
@@ -396,7 +330,7 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -428,7 +362,7 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -449,7 +383,7 @@
* @param device BluetoothDevice device
*/
public boolean isA2dpPlaying(BluetoothDevice device) {
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.isA2dpPlaying(device);
@@ -488,25 +422,6 @@
}
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK,
- BluetoothA2dpSink.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP_SINK);
- }
- }
- };
-
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
index c447868..4e7e441 100644
--- a/core/java/android/bluetooth/BluetoothAvrcpController.java
+++ b/core/java/android/bluetooth/BluetoothAvrcpController.java
@@ -16,14 +16,10 @@
package android.bluetooth;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -80,93 +76,32 @@
public static final String EXTRA_PLAYER_SETTING =
"android.bluetooth.avrcp-controller.profile.extra.PLAYER_SETTING";
- private Context mContext;
- private ServiceListener mServiceListener;
- private volatile IBluetoothAvrcpController mService;
private BluetoothAdapter mAdapter;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private final BluetoothProfileConnector<IBluetoothAvrcpController> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.AVRCP_CONTROLLER,
+ "BluetoothAvrcpController", IBluetoothAvrcpController.class.getName()) {
+ @Override
+ public IBluetoothAvrcpController getServiceInterface(IBinder service) {
+ return IBluetoothAvrcpController.Stub.asInterface(
+ Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothAvrcpController proxy object for interacting with the local
* Bluetooth AVRCP service.
*/
- /*package*/ BluetoothAvrcpController(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothAvrcpController(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothAvrcpController.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth AVRCP Controller Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
- mServiceListener = null;
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private IBluetoothAvrcpController getService() {
+ return mProfileConnector.getService();
}
@Override
@@ -180,7 +115,8 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -199,7 +135,8 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -218,7 +155,8 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -239,7 +177,8 @@
public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getPlayerSettings");
BluetoothAvrcpPlayerSettings settings = null;
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled()) {
try {
settings = service.getPlayerSettings(device);
@@ -257,7 +196,8 @@
*/
public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) {
if (DBG) Log.d(TAG, "setPlayerApplicationSetting");
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.setPlayerApplicationSetting(plAppSetting);
@@ -277,7 +217,8 @@
public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) {
Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = "
+ keyState);
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled()) {
try {
service.sendGroupNavigationCmd(device, keyCode, keyState);
@@ -290,25 +231,6 @@
if (service == null) Log.w(TAG, "Proxy not attached to service");
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothAvrcpController.Stub.asInterface(Binder.allowBlocking(service));
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER,
- BluetoothAvrcpController.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.AVRCP_CONTROLLER);
- }
- }
- };
-
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 8d9d340..9862a63 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -337,19 +337,9 @@
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
doUnbind();
} else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
+ doBind();
}
}
};
@@ -374,24 +364,32 @@
doBind();
}
- boolean doBind() {
- try {
- return mAdapter.getBluetoothManager().bindBluetoothProfileService(
- BluetoothProfile.HEADSET, mConnection);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to bind HeadsetService", e);
+ private boolean doBind() {
+ synchronized (mConnection) {
+ if (mService == null) {
+ if (VDBG) Log.d(TAG, "Binding service...");
+ try {
+ return mAdapter.getBluetoothManager().bindBluetoothProfileService(
+ BluetoothProfile.HEADSET, mConnection);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to bind HeadsetService", e);
+ }
+ }
}
return false;
}
- void doUnbind() {
+ private void doUnbind() {
synchronized (mConnection) {
if (mService != null) {
+ if (VDBG) Log.d(TAG, "Unbinding service...");
try {
mAdapter.getBluetoothManager().unbindBluetoothProfileService(
BluetoothProfile.HEADSET, mConnection);
} catch (RemoteException e) {
Log.e(TAG, "Unable to unbind HeadsetService", e);
+ } finally {
+ mService = null;
}
}
}
@@ -411,8 +409,8 @@
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
+ } catch (RemoteException re) {
+ Log.e(TAG, "", re);
}
}
mServiceListener = null;
@@ -1169,7 +1167,7 @@
@Override
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
+ doUnbind();
mHandler.sendMessage(mHandler.obtainMessage(
MESSAGE_HEADSET_SERVICE_DISCONNECTED));
}
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 549c1fa..05833b5 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -17,15 +17,11 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -367,73 +363,22 @@
public static final int CALL_ACCEPT_HOLD = 1;
public static final int CALL_ACCEPT_TERMINATE = 2;
- private Context mContext;
- private ServiceListener mServiceListener;
- private volatile IBluetoothHeadsetClient mService;
private BluetoothAdapter mAdapter;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
+ private final BluetoothProfileConnector<IBluetoothHeadsetClient> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.HEADSET_CLIENT,
+ "BluetoothHeadsetClient", IBluetoothHeadsetClient.class.getName()) {
@Override
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- Intent intent = new Intent(
- IBluetoothHeadsetClient.class.getName());
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ public IBluetoothHeadsetClient getServiceInterface(IBinder service) {
+ return IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothHeadsetClient proxy object.
*/
- /*package*/ BluetoothHeadsetClient(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothHeadsetClient(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothHeadsetClient.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
/**
@@ -444,27 +389,11 @@
*/
/*package*/ void close() {
if (VDBG) log("close()");
+ mProfileConnector.disconnect();
+ }
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
-
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothHeadsetClient getService() {
+ return mProfileConnector.getService();
}
/**
@@ -481,7 +410,8 @@
@UnsupportedAppUsage
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -504,7 +434,8 @@
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -525,7 +456,8 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -548,7 +480,8 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -570,7 +503,8 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getConnectionState(" + device + ")");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -590,7 +524,8 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -612,7 +547,8 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -638,7 +574,8 @@
*/
public boolean startVoiceRecognition(BluetoothDevice device) {
if (DBG) log("startVoiceRecognition()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.startVoiceRecognition(device);
@@ -663,7 +600,8 @@
*/
public boolean stopVoiceRecognition(BluetoothDevice device) {
if (DBG) log("stopVoiceRecognition()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.stopVoiceRecognition(device);
@@ -683,7 +621,8 @@
*/
public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getCurrentCalls(device);
@@ -703,7 +642,8 @@
*/
public Bundle getCurrentAgEvents(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getCurrentAgEvents(device);
@@ -727,7 +667,8 @@
@UnsupportedAppUsage
public boolean acceptCall(BluetoothDevice device, int flag) {
if (DBG) log("acceptCall()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.acceptCall(device, flag);
@@ -748,7 +689,8 @@
*/
public boolean holdCall(BluetoothDevice device) {
if (DBG) log("holdCall()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.holdCall(device);
@@ -774,7 +716,8 @@
@UnsupportedAppUsage
public boolean rejectCall(BluetoothDevice device) {
if (DBG) log("rejectCall()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.rejectCall(device);
@@ -804,7 +747,8 @@
*/
public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
if (DBG) log("terminateCall()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.terminateCall(device, call);
@@ -832,7 +776,8 @@
*/
public boolean enterPrivateMode(BluetoothDevice device, int index) {
if (DBG) log("enterPrivateMode()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.enterPrivateMode(device, index);
@@ -859,7 +804,8 @@
*/
public boolean explicitCallTransfer(BluetoothDevice device) {
if (DBG) log("explicitCallTransfer()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.explicitCallTransfer(device);
@@ -882,7 +828,8 @@
*/
public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
if (DBG) log("dial()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.dial(device, number);
@@ -906,7 +853,8 @@
*/
public boolean sendDTMF(BluetoothDevice device, byte code) {
if (DBG) log("sendDTMF()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.sendDTMF(device, code);
@@ -932,7 +880,8 @@
*/
public boolean getLastVoiceTagNumber(BluetoothDevice device) {
if (DBG) log("getLastVoiceTagNumber()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getLastVoiceTagNumber(device);
@@ -952,7 +901,8 @@
@UnsupportedAppUsage
public int getAudioState(BluetoothDevice device) {
if (VDBG) log("getAudioState");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getAudioState(device);
@@ -975,7 +925,8 @@
*/
public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) {
if (VDBG) log("setAudioRouteAllowed");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
service.setAudioRouteAllowed(device, allowed);
@@ -997,7 +948,8 @@
*/
public boolean getAudioRouteAllowed(BluetoothDevice device) {
if (VDBG) log("getAudioRouteAllowed");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getAudioRouteAllowed(device);
@@ -1021,7 +973,8 @@
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
public boolean connectAudio(BluetoothDevice device) {
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.connectAudio(device);
@@ -1045,7 +998,8 @@
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
public boolean disconnectAudio(BluetoothDevice device) {
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.disconnectAudio(device);
@@ -1066,7 +1020,8 @@
* @return bundle of AG features; null if no service or AG not connected
*/
public Bundle getCurrentAgFeatures(BluetoothDevice device) {
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getCurrentAgFeatures(device);
@@ -1080,29 +1035,6 @@
return null;
}
-
- private final ServiceConnection mConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service));
-
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT,
- BluetoothHeadsetClient.this);
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET_CLIENT);
- }
- }
- };
-
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index d6edb90..60fb6fb 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -22,21 +22,14 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
-import com.android.internal.annotations.GuardedBy;
-
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* This class provides the public APIs to control the Hearing Aid profile.
@@ -129,97 +122,31 @@
*/
public static final long HI_SYNC_ID_INVALID = IBluetoothHearingAid.HI_SYNC_ID_INVALID;
- private Context mContext;
- private ServiceListener mServiceListener;
- private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
- @GuardedBy("mServiceLock")
- private IBluetoothHearingAid mService;
private BluetoothAdapter mAdapter;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- try {
- mServiceLock.writeLock().lock();
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.writeLock().unlock();
- }
- } else {
- try {
- mServiceLock.readLock().lock();
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.readLock().unlock();
- }
- }
+ private final BluetoothProfileConnector<IBluetoothHearingAid> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.HEARING_AID,
+ "BluetoothHearingAid", IBluetoothHearingAid.class.getName()) {
+ @Override
+ public IBluetoothHearingAid getServiceInterface(IBinder service) {
+ return IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothHearingAid proxy object for interacting with the local
* Bluetooth Hearing Aid service.
*/
- /*package*/ BluetoothHearingAid(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothHearingAid(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- void doBind() {
- Intent intent = new Intent(IBluetoothHearingAid.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth Hearing Aid Service with " + intent);
- return;
- }
+ mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
- mServiceListener = null;
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- try {
- mServiceLock.writeLock().lock();
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.writeLock().unlock();
- }
+ private IBluetoothHearingAid getService() {
+ return mProfileConnector.getService();
}
/**
@@ -241,18 +168,16 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.connect(device);
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.connect(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -283,18 +208,16 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.disconnect(device);
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.disconnect(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -304,18 +227,16 @@
@Override
public @NonNull List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getConnectedDevices();
+ if (service != null && isEnabled()) {
+ return service.getConnectedDevices();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -326,18 +247,16 @@
public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
@NonNull int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getDevicesMatchingConnectionStates(states);
+ if (service != null && isEnabled()) {
+ return service.getDevicesMatchingConnectionStates(states);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -348,19 +267,17 @@
public @BluetoothProfile.BtProfileState int getConnectionState(
@NonNull BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -388,20 +305,18 @@
*/
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& ((device == null) || isValidDevice(device))) {
- mService.setActiveDevice(device);
+ service.setActiveDevice(device);
return true;
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -419,18 +334,16 @@
@RequiresPermission(Manifest.permission.BLUETOOTH)
public List<BluetoothDevice> getActiveDevices() {
if (VDBG) log("getActiveDevices()");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getActiveDevices();
+ if (service != null && isEnabled()) {
+ return service.getActiveDevices();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<>();
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -451,23 +364,21 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -485,19 +396,17 @@
@RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getPriority(device);
+ return service.getPriority(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.PRIORITY_OFF;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.PRIORITY_OFF;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -536,18 +445,16 @@
if (VDBG) {
log("getVolume()");
}
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getVolume();
+ if (service != null && isEnabled()) {
+ return service.getVolume();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return 0;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return 0;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -567,21 +474,18 @@
public void adjustVolume(int direction) {
if (DBG) log("adjustVolume(" + direction + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
-
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return;
}
if (!isEnabled()) return;
- mService.adjustVolume(direction);
+ service.adjustVolume(direction);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -594,20 +498,18 @@
public void setVolume(int volume) {
if (DBG) Log.d(TAG, "setVolume(" + volume + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return;
}
if (!isEnabled()) return;
- mService.setVolume(volume);
+ service.setVolume(volume);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -623,21 +525,19 @@
if (VDBG) {
log("getCustomerId(" + device + ")");
}
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return HI_SYNC_ID_INVALID;
}
if (!isEnabled() || !isValidDevice(device)) return HI_SYNC_ID_INVALID;
- return mService.getHiSyncId(device);
+ return service.getHiSyncId(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return HI_SYNC_ID_INVALID;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -653,19 +553,17 @@
if (VDBG) {
log("getDeviceSide(" + device + ")");
}
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getDeviceSide(device);
+ return service.getDeviceSide(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return SIDE_LEFT;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return SIDE_LEFT;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -681,52 +579,20 @@
if (VDBG) {
log("getDeviceMode(" + device + ")");
}
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getDeviceMode(device);
+ return service.getDeviceMode(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return MODE_MONAURAL;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return MODE_MONAURAL;
- } finally {
- mServiceLock.readLock().unlock();
}
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- try {
- mServiceLock.writeLock().lock();
- mService = IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service));
- } finally {
- mServiceLock.writeLock().unlock();
- }
-
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.HEARING_AID,
- BluetoothHearingAid.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- try {
- mServiceLock.writeLock().lock();
- mService = null;
- } finally {
- mServiceLock.writeLock().unlock();
- }
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.HEARING_AID);
- }
- }
- };
-
private boolean isEnabled() {
if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
return false;
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
index e44f36e..e9b0be2 100644
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ b/core/java/android/bluetooth/BluetoothHidDevice.java
@@ -18,13 +18,10 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
+import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -328,11 +325,6 @@
}
}
- private Context mContext;
- private ServiceListener mServiceListener;
- private volatile IBluetoothHidDevice mService;
- private BluetoothAdapter mAdapter;
-
private static class CallbackWrapper extends IBluetoothHidDeviceCallback.Stub {
private final Executor mExecutor;
@@ -386,114 +378,33 @@
}
}
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
-
- public void onBluetoothStateChange(boolean up) {
- Log.d(TAG, "onBluetoothStateChange: up=" + up);
- synchronized (mConnection) {
- if (up) {
- try {
- if (mService == null) {
- Log.d(TAG, "Binding HID Device service...");
- doBind();
- }
- } catch (IllegalStateException e) {
- Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev "
- + "service: ", e);
- } catch (SecurityException e) {
- Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev "
- + "service: ", e);
- }
- } else {
- Log.d(TAG, "Unbinding service...");
- doUnbind();
- }
- }
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothHidDevice> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.HID_DEVICE,
+ "BluetoothHidDevice", IBluetoothHidDevice.class.getName()) {
+ @Override
+ public IBluetoothHidDevice getServiceInterface(IBinder service) {
+ return IBluetoothHidDevice.Stub.asInterface(Binder.allowBlocking(service));
}
- };
-
- private final ServiceConnection mConnection =
- new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- Log.d(TAG, "onServiceConnected()");
- mService = IBluetoothHidDevice.Stub.asInterface(service);
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(
- BluetoothProfile.HID_DEVICE, BluetoothHidDevice.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- Log.d(TAG, "onServiceDisconnected()");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.HID_DEVICE);
- }
- }
- };
+ };
BluetoothHidDevice(Context context, ServiceListener listener) {
- mContext = context;
- mServiceListener = listener;
mAdapter = BluetoothAdapter.getDefaultAdapter();
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothHidDevice.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent);
- return false;
- }
- Log.d(TAG, "Bound to HID Device Service");
- return true;
- }
-
- void doUnbind() {
- if (mService != null) {
- mService = null;
- try {
- mContext.unbindService(mConnection);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Unable to unbind HidDevService", e);
- }
- }
+ mProfileConnector.connect(context, listener);
}
void close() {
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- doUnbind();
- }
- mServiceListener = null;
+ private IBluetoothHidDevice getService() {
+ return mProfileConnector.getService();
}
/** {@inheritDoc} */
@Override
public List<BluetoothDevice> getConnectedDevices() {
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
return service.getConnectedDevices();
@@ -510,7 +421,7 @@
/** {@inheritDoc} */
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -527,7 +438,7 @@
/** {@inheritDoc} */
@Override
public int getConnectionState(BluetoothDevice device) {
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
return service.getConnectionState(device);
@@ -584,7 +495,7 @@
throw new IllegalArgumentException("callback parameter cannot be null");
}
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
CallbackWrapper cbw = new CallbackWrapper(executor, callback);
@@ -612,7 +523,7 @@
public boolean unregisterApp() {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.unregisterApp();
@@ -637,7 +548,7 @@
public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.sendReport(device, id, data);
@@ -663,7 +574,7 @@
public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.replyReport(device, type, id, data);
@@ -687,7 +598,7 @@
public boolean reportError(BluetoothDevice device, byte error) {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.reportError(device, error);
@@ -708,7 +619,7 @@
* {@hide}
*/
public String getUserAppName() {
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
@@ -734,7 +645,7 @@
public boolean connect(BluetoothDevice device) {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.connect(device);
@@ -758,7 +669,7 @@
public boolean disconnect(BluetoothDevice device) {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.disconnect(device);
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
index 7c925a1..4afb382 100644
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ b/core/java/android/bluetooth/BluetoothHidHost.java
@@ -18,14 +18,10 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -220,97 +216,32 @@
public static final String EXTRA_IDLE_TIME =
"android.bluetooth.BluetoothHidHost.extra.IDLE_TIME";
- private Context mContext;
- private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
- private volatile IBluetoothHidHost mService;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private final BluetoothProfileConnector<IBluetoothHidHost> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.HID_HOST,
+ "BluetoothHidHost", IBluetoothHidHost.class.getName()) {
+ @Override
+ public IBluetoothHidHost getServiceInterface(IBinder service) {
+ return IBluetoothHidHost.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothHidHost proxy object for interacting with the local
* Bluetooth Service which handles the InputDevice profile
*/
- /*package*/ BluetoothHidHost(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothHidHost(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothHidHost.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
if (VDBG) log("close()");
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothHidHost getService() {
+ return mProfileConnector.getService();
}
/**
@@ -334,7 +265,7 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -374,7 +305,7 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -393,7 +324,7 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -412,7 +343,7 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -431,7 +362,7 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -461,7 +392,7 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -493,7 +424,7 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -506,26 +437,6 @@
return BluetoothProfile.PRIORITY_OFF;
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothHidHost.Stub.asInterface(Binder.allowBlocking(service));
-
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.HID_HOST,
- BluetoothHidHost.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.HID_HOST);
- }
- }
- };
-
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
@@ -545,7 +456,7 @@
*/
public boolean virtualUnplug(BluetoothDevice device) {
if (DBG) log("virtualUnplug(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.virtualUnplug(device);
@@ -571,7 +482,7 @@
*/
public boolean getProtocolMode(BluetoothDevice device) {
if (VDBG) log("getProtocolMode(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getProtocolMode(device);
@@ -595,7 +506,7 @@
*/
public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
if (DBG) log("setProtocolMode(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.setProtocolMode(device, protocolMode);
@@ -626,7 +537,7 @@
log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId
+ "bufferSize=" + bufferSize);
}
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getReport(device, reportType, reportId, bufferSize);
@@ -652,7 +563,7 @@
*/
public boolean setReport(BluetoothDevice device, byte reportType, String report) {
if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.setReport(device, reportType, report);
@@ -677,7 +588,7 @@
*/
public boolean sendData(BluetoothDevice device, String report) {
if (DBG) log("sendData(" + device + "), report=" + report);
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.sendData(device, report);
@@ -701,7 +612,7 @@
*/
public boolean getIdleTime(BluetoothDevice device) {
if (DBG) log("getIdletime(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getIdleTime(device);
@@ -726,7 +637,7 @@
*/
public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime);
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.setIdleTime(device, idleTime);
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index fc5f830..dd2f150 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -17,14 +17,10 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -45,11 +41,6 @@
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
- private volatile IBluetoothMap mService;
- private final Context mContext;
- private ServiceListener mServiceListener;
- private BluetoothAdapter mAdapter;
-
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
@@ -58,64 +49,23 @@
/** Connection canceled before completion. */
public static final int RESULT_CANCELED = 2;
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothMap> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.MAP,
+ "BluetoothMap", IBluetoothMap.class.getName()) {
+ @Override
+ public IBluetoothMap getServiceInterface(IBinder service) {
+ return IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothMap proxy object.
*/
- /*package*/ BluetoothMap(Context context, ServiceListener l) {
+ /*package*/ BluetoothMap(Context context, ServiceListener listener) {
if (DBG) Log.d(TAG, "Create BluetoothMap proxy object");
- mContext = context;
- mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothMap.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -133,26 +83,11 @@
* are ok.
*/
public synchronized void close() {
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothMap getService() {
+ return mProfileConnector.getService();
}
/**
@@ -163,7 +98,7 @@
*/
public int getState() {
if (VDBG) log("getState()");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null) {
try {
return service.getState();
@@ -185,7 +120,7 @@
*/
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null) {
try {
return service.getClient();
@@ -206,7 +141,7 @@
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null) {
try {
return service.isConnected(device);
@@ -238,7 +173,7 @@
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -279,7 +214,7 @@
*/
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -299,7 +234,7 @@
*/
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -319,7 +254,7 @@
*/
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -345,7 +280,7 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -374,7 +309,7 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -387,24 +322,6 @@
return PRIORITY_OFF;
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) log("Proxy object connected");
- mService = IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service));
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) log("Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.MAP);
- }
- }
- };
-
private static void log(String msg) {
Log.d(TAG, msg);
}
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 1c82e19..ec0180c5 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -18,14 +18,11 @@
import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.net.Uri;
+import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -61,11 +58,6 @@
public static final String EXTRA_SENDER_CONTACT_NAME =
"android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
- private volatile IBluetoothMapClient mService;
- private final Context mContext;
- private ServiceListener mServiceListener;
- private BluetoothAdapter mAdapter;
-
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
@@ -76,64 +68,23 @@
private static final int UPLOADING_FEATURE_BITMASK = 0x08;
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothMapClient> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.MAP_CLIENT,
+ "BluetoothMapClient", IBluetoothMapClient.class.getName()) {
+ @Override
+ public IBluetoothMapClient getServiceInterface(IBinder service) {
+ return IBluetoothMapClient.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothMapClient proxy object.
*/
- /*package*/ BluetoothMapClient(Context context, ServiceListener l) {
+ /*package*/ BluetoothMapClient(Context context, ServiceListener listener) {
if (DBG) Log.d(TAG, "Create BluetoothMapClient proxy object");
- mContext = context;
- mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothMapClient.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth MAP MCE Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -151,26 +102,11 @@
* are ok.
*/
public void close() {
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothMapClient getService() {
+ return mProfileConnector.getService();
}
/**
@@ -180,7 +116,7 @@
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null) {
try {
return service.isConnected(device);
@@ -200,7 +136,7 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null) {
try {
return service.connect(device);
@@ -222,7 +158,7 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) Log.d(TAG, "disconnect(" + device + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -242,7 +178,7 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) Log.d(TAG, "getConnectedDevices()");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -263,7 +199,7 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -284,7 +220,7 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -308,7 +244,7 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -337,7 +273,7 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -366,7 +302,7 @@
public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
PendingIntent sentIntent, PendingIntent deliveredIntent) {
if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
@@ -386,7 +322,7 @@
*/
public boolean getUnreadMessages(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getUnreadMessages(device);
@@ -406,34 +342,16 @@
* MapSupportedFeatures field is set. False is returned otherwise.
*/
public boolean isUploadingSupported(BluetoothDevice device) {
+ final IBluetoothMapClient service = getService();
try {
- return (mService != null && isEnabled() && isValidDevice(device))
- && ((mService.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0);
+ return (service != null && isEnabled() && isValidDevice(device))
+ && ((service.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
return false;
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothMapClient.Stub.asInterface(service);
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT,
- BluetoothMapClient.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.MAP_CLIENT);
- }
- }
- };
-
private boolean isEnabled() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true;
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 8923d73..fb78789 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -19,14 +19,10 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -122,108 +118,42 @@
*/
public static final int PAN_OPERATION_SUCCESS = 1004;
- private Context mContext;
- private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
- private volatile IBluetoothPan mPanService;
+ private final BluetoothProfileConnector<IBluetoothPan> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.PAN,
+ "BluetoothPan", IBluetoothPan.class.getName()) {
+ @Override
+ public IBluetoothPan getServiceInterface(IBinder service) {
+ return IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service));
+ }
+ };
+
/**
* Create a BluetoothPan proxy object for interacting with the local
* Bluetooth Service which handles the Pan profile
*/
@UnsupportedAppUsage
- /*package*/ BluetoothPan(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothPan(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- try {
- mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback);
- } catch (RemoteException re) {
- Log.w(TAG, "Unable to register BluetoothStateChangeCallback", re);
- }
- if (VDBG) Log.d(TAG, "BluetoothPan() call bindService");
- doBind();
- }
-
- @UnsupportedAppUsage
- boolean doBind() {
- Intent intent = new Intent(IBluetoothPan.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth Pan Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
@UnsupportedAppUsage
/*package*/ void close() {
if (VDBG) log("close()");
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mStateChangeCallback);
- } catch (RemoteException re) {
- Log.w(TAG, "Unable to unregister BluetoothStateChangeCallback", re);
- }
- }
-
- synchronized (mConnection) {
- if (mPanService != null) {
- try {
- mPanService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ mProfileConnector.disconnect();
}
+ private IBluetoothPan getService() {
+ return mProfileConnector.getService();
+ }
+
+
protected void finalize() {
close();
}
- private final IBluetoothStateChangeCallback mStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
-
- @Override
- public void onBluetoothStateChange(boolean on) {
- // Handle enable request to bind again.
- Log.d(TAG, "onBluetoothStateChange on: " + on);
- if (on) {
- try {
- if (mPanService == null) {
- if (VDBG) Log.d(TAG, "onBluetoothStateChange calling doBind()");
- doBind();
- }
-
- } catch (IllegalStateException e) {
- Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ",
- e);
-
- } catch (SecurityException e) {
- Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ",
- e);
- }
- } else {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mPanService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- }
- };
-
/**
* Initiate connection to a profile of the remote bluetooth device.
*
@@ -244,7 +174,7 @@
@UnsupportedAppUsage
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -285,7 +215,7 @@
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -304,7 +234,7 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -323,7 +253,7 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -342,7 +272,7 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -358,7 +288,7 @@
@UnsupportedAppUsage
public void setBluetoothTethering(boolean value) {
if (DBG) log("setBluetoothTethering(" + value + ")");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
service.setBluetoothTethering(value);
@@ -371,7 +301,7 @@
@UnsupportedAppUsage
public boolean isTetheringOn() {
if (VDBG) log("isTetheringOn()");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
return service.isTetheringOn();
@@ -382,25 +312,6 @@
return false;
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected");
- mPanService = IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service));
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.PAN,
- BluetoothPan.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "BluetoothPAN Proxy object disconnected");
- mPanService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.PAN);
- }
- }
- };
-
@UnsupportedAppUsage
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index 359bec6..d94c657 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -118,28 +118,9 @@
public void onBluetoothStateChange(boolean up) {
log("onBluetoothStateChange: up=" + up);
if (!up) {
- log("Unbinding service...");
- synchronized (mConnection) {
- try {
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
+ doUnbind();
} else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- log("Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
+ doBind();
}
}
};
@@ -155,25 +136,51 @@
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
+ } catch (RemoteException re) {
+ Log.e(TAG, "", re);
}
}
doBind();
}
boolean doBind() {
- Intent intent = new Intent(IBluetoothPbap.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
- return false;
+ synchronized (mConnection) {
+ try {
+ if (mService == null) {
+ log("Binding service...");
+ Intent intent = new Intent(IBluetoothPbap.class.getName());
+ ComponentName comp = intent.resolveSystemService(
+ mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+ UserHandle.CURRENT_OR_SELF)) {
+ Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
+ return false;
+ }
+ }
+ } catch (SecurityException se) {
+ Log.e(TAG, "", se);
+ return false;
+ }
}
return true;
}
+ private void doUnbind() {
+ synchronized (mConnection) {
+ if (mService != null) {
+ log("Unbinding service...");
+ try {
+ mContext.unbindService(mConnection);
+ } catch (IllegalArgumentException ie) {
+ Log.e(TAG, "", ie);
+ } finally {
+ mService = null;
+ }
+ }
+ }
+ }
+
protected void finalize() throws Throwable {
try {
close();
@@ -193,21 +200,11 @@
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
+ } catch (RemoteException re) {
+ Log.e(TAG, "", re);
}
}
-
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ doUnbind();
mServiceListener = null;
}
@@ -313,7 +310,7 @@
public void onServiceDisconnected(ComponentName className) {
log("Proxy object disconnected");
- mService = null;
+ doUnbind();
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected();
}
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index cbc96c0..d70e1e7 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -16,14 +16,10 @@
package android.bluetooth;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -43,11 +39,6 @@
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED";
- private volatile IBluetoothPbapClient mService;
- private final Context mContext;
- private ServiceListener mServiceListener;
- private BluetoothAdapter mAdapter;
-
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
@@ -56,72 +47,25 @@
/** Connection canceled before completion. */
public static final int RESULT_CANCELED = 2;
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) {
- Log.d(TAG, "onBluetoothStateChange: PBAP CLIENT up=" + up);
- }
- if (!up) {
- if (VDBG) {
- Log.d(TAG, "Unbinding service...");
- }
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) {
- Log.d(TAG, "Binding service...");
- }
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothPbapClient> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.PBAP_CLIENT,
+ "BluetoothPbapClient", IBluetoothPbapClient.class.getName()) {
+ @Override
+ public IBluetoothPbapClient getServiceInterface(IBinder service) {
+ return IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothPbapClient proxy object.
*/
- BluetoothPbapClient(Context context, ServiceListener l) {
+ BluetoothPbapClient(Context context, ServiceListener listener) {
if (DBG) {
Log.d(TAG, "Create BluetoothPbapClient proxy object");
}
- mContext = context;
- mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- doBind();
- }
-
- private boolean doBind() {
- Intent intent = new Intent(IBluetoothPbapClient.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth PBAP Client Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -139,26 +83,11 @@
* are ok.
*/
public synchronized void close() {
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothPbapClient getService() {
+ return mProfileConnector.getService();
}
/**
@@ -174,7 +103,7 @@
if (DBG) {
log("connect(" + device + ") for PBAP Client.");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -199,7 +128,7 @@
if (DBG) {
log("disconnect(" + device + ")" + new Exception());
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
service.disconnect(device);
@@ -226,7 +155,7 @@
if (DBG) {
log("getConnectedDevices()");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -251,7 +180,7 @@
if (DBG) {
log("getDevicesMatchingStates()");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -276,7 +205,7 @@
if (DBG) {
log("getConnectionState(" + device + ")");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -291,29 +220,6 @@
return BluetoothProfile.STATE_DISCONNECTED;
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) {
- log("Proxy object connected");
- }
- mService = IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT,
- BluetoothPbapClient.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) {
- log("Proxy object disconnected");
- }
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP_CLIENT);
- }
- }
- };
-
private static void log(String msg) {
Log.d(TAG, msg);
}
@@ -346,7 +252,7 @@
if (DBG) {
log("setPriority(" + device + ", " + priority + ")");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -379,7 +285,7 @@
if (VDBG) {
log("getPriority(" + device + ")");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
diff --git a/core/java/android/bluetooth/BluetoothProfileConnector.java b/core/java/android/bluetooth/BluetoothProfileConnector.java
new file mode 100644
index 0000000..d9987249
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothProfileConnector.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+/**
+ * Connector for Bluetooth profile proxies to bind manager service and
+ * profile services
+ * @param <T> The Bluetooth profile interface for this connection.
+ * @hide
+ */
+public abstract class BluetoothProfileConnector<T> {
+ private int mProfileId;
+ private BluetoothProfile.ServiceListener mServiceListener;
+ private BluetoothProfile mProfileProxy;
+ private Context mContext;
+ private String mProfileName;
+ private String mServiceName;
+ private volatile T mService;
+
+ private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+ new IBluetoothStateChangeCallback.Stub() {
+ public void onBluetoothStateChange(boolean up) {
+ if (up) {
+ doBind();
+ } else {
+ doUnbind();
+ }
+ }
+ };
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ logDebug("Proxy object connected");
+ mService = getServiceInterface(service);
+
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(mProfileId, mProfileProxy);
+ }
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ logDebug("Proxy object disconnected");
+ doUnbind();
+ if (mServiceListener != null) {
+ mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
+ }
+ }
+ };
+
+ BluetoothProfileConnector(BluetoothProfile profile, int profileId, String profileName,
+ String serviceName) {
+ mProfileId = profileId;
+ mProfileProxy = profile;
+ mProfileName = profileName;
+ mServiceName = serviceName;
+ }
+
+ private boolean doBind() {
+ synchronized (mConnection) {
+ if (mService == null) {
+ logDebug("Binding service...");
+ try {
+ Intent intent = new Intent(mServiceName);
+ ComponentName comp = intent.resolveSystemService(
+ mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+ UserHandle.CURRENT_OR_SELF)) {
+ logError("Could not bind to Bluetooth Service with " + intent);
+ return false;
+ }
+ } catch (SecurityException se) {
+ logError("Failed to bind service. " + se);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private void doUnbind() {
+ synchronized (mConnection) {
+ if (mService != null) {
+ logDebug("Unbinding service...");
+ try {
+ mContext.unbindService(mConnection);
+ } catch (IllegalArgumentException ie) {
+ logError("Unable to unbind service: " + ie);
+ } finally {
+ mService = null;
+ }
+ }
+ }
+ }
+
+ void connect(Context context, BluetoothProfile.ServiceListener listener) {
+ mContext = context;
+ mServiceListener = listener;
+ IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException re) {
+ logError("Failed to register state change callback. " + re);
+ }
+ }
+ doBind();
+ }
+
+ void disconnect() {
+ mServiceListener = null;
+ IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException re) {
+ logError("Failed to unregister state change callback" + re);
+ }
+ }
+ doUnbind();
+ }
+
+ T getService() {
+ return mService;
+ }
+
+ /**
+ * This abstract function is used to implement method to get the
+ * connected Bluetooth service interface.
+ * @param service the connected binder service.
+ * @return T the binder interface of {@code service}.
+ * @hide
+ */
+ public abstract T getServiceInterface(IBinder service);
+
+ private void logDebug(String log) {
+ Log.d(mProfileName, log);
+ }
+
+ private void logError(String log) {
+ Log.e(mProfileName, log);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index ebf6bed..e0610c8 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -17,14 +17,10 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -70,11 +66,6 @@
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
- private volatile IBluetoothSap mService;
- private final Context mContext;
- private ServiceListener mServiceListener;
- private BluetoothAdapter mAdapter;
-
/**
* There was an error trying to obtain the state.
*
@@ -96,64 +87,23 @@
*/
public static final int RESULT_CANCELED = 2;
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothSap> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.SAP,
+ "BluetoothSap", IBluetoothSap.class.getName()) {
+ @Override
+ public IBluetoothSap getServiceInterface(IBinder service) {
+ return IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothSap proxy object.
*/
- /*package*/ BluetoothSap(Context context, ServiceListener l) {
+ /*package*/ BluetoothSap(Context context, ServiceListener listener) {
if (DBG) Log.d(TAG, "Create BluetoothSap proxy object");
- mContext = context;
- mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothSap.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth SAP Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -173,26 +123,11 @@
* @hide
*/
public synchronized void close() {
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothSap getService() {
+ return mProfileConnector.getService();
}
/**
@@ -204,7 +139,7 @@
*/
public int getState() {
if (VDBG) log("getState()");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null) {
try {
return service.getState();
@@ -227,7 +162,7 @@
*/
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null) {
try {
return service.getClient();
@@ -250,7 +185,7 @@
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null) {
try {
return service.isConnected(device);
@@ -285,7 +220,7 @@
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -306,7 +241,7 @@
*/
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -327,7 +262,7 @@
*/
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -348,7 +283,7 @@
*/
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -373,7 +308,7 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -399,7 +334,7 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -412,24 +347,6 @@
return PRIORITY_OFF;
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) log("Proxy object connected");
- mService = IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.SAP, BluetoothSap.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) log("Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.SAP);
- }
- }
- };
-
private static void log(String msg) {
Log.d(TAG, msg);
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 8046776..2c5860a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -825,7 +825,9 @@
* @param sortOrder How to order the rows, formatted as an SQL ORDER BY
* clause (excluding the ORDER BY itself). Passing null will use the
* default sort order, which may be unordered.
- * @return A Cursor object, which is positioned before the first entry, or null
+ * @return A Cursor object, which is positioned before the first entry. May return
+ * <code>null</code> if the underlying content provider returns <code>null</code>,
+ * or if it crashes.
* @see Cursor
*/
public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
@@ -865,7 +867,9 @@
* @param cancellationSignal A signal to cancel the operation in progress, or null if none.
* If the operation is canceled, then {@link OperationCanceledException} will be thrown
* when the query is executed.
- * @return A Cursor object, which is positioned before the first entry, or null
+ * @return A Cursor object, which is positioned before the first entry. May return
+ * <code>null</code> if the underlying content provider returns <code>null</code>,
+ * or if it crashes.
* @see Cursor
*/
public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
@@ -902,7 +906,9 @@
* @param cancellationSignal A signal to cancel the operation in progress, or null if none.
* If the operation is canceled, then {@link OperationCanceledException} will be thrown
* when the query is executed.
- * @return A Cursor object, which is positioned before the first entry, or null
+ * @return A Cursor object, which is positioned before the first entry. May return
+ * <code>null</code> if the underlying content provider returns <code>null</code>,
+ * or if it crashes.
* @see Cursor
*/
@Override
@@ -1799,7 +1805,8 @@
* @param url The URL of the table to insert into.
* @param values The initial values for the newly inserted row. The key is the column name for
* the field. Passing an empty ContentValues will create an empty row.
- * @return the URL of the newly created row.
+ * @return the URL of the newly created row. May return <code>null</code> if the underlying
+ * content provider returns <code>null</code>, or if it crashes.
*/
@Override
public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 0112396..654e698 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -329,15 +329,6 @@
public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080;
/**
- * Flag for {@link #bindService}: If binding from something better than perceptible,
- * still set the adjust below perceptible. This would be used for bound services that can
- * afford to be evicted when under extreme memory pressure, but should be restarted as soon
- * as possible.
- * @hide
- */
- public static final int BIND_ADJUST_BELOW_PERCEPTIBLE = 0x0100;
-
- /**
* Flag for {@link #bindService}: If binding from an app that has specific capabilities
* due to its foreground state such as an activity or foreground service, then this flag will
* allow the bound app to get the same capabilities, as long as it has the required permissions
@@ -345,6 +336,18 @@
*/
public static final int BIND_INCLUDE_CAPABILITIES = 0x00001000;
+ /*********** Public flags above this line ***********/
+ /*********** Hidden flags below this line ***********/
+
+ /**
+ * Flag for {@link #bindService}: If binding from something better than perceptible,
+ * still set the adjust below perceptible. This would be used for bound services that can
+ * afford to be evicted when under extreme memory pressure, but should be restarted as soon
+ * as possible.
+ * @hide
+ */
+ public static final int BIND_ADJUST_BELOW_PERCEPTIBLE = 0x00040000;
+
/**
* Flag for {@link #bindService}: This flag is intended to be used only by the system to adjust
* the scheduling policy for IMEs (and any other out-of-process user-visible components that
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3898328..9e5fcfb 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1881,6 +1881,31 @@
"android.intent.action.REVIEW_PERMISSIONS";
/**
+ * Activity action: Launch UI to show information about the usage
+ * of a given permission. This action would be handled by apps that
+ * want to show details about how and why given permission is being
+ * used.
+ * <p>
+ * <strong>Important:</strong>You must protect the activity that handles
+ * this action with the {@link android.Manifest.permission#START_VIEW_PERMISSION_USAGE
+ * START_VIEW_PERMISSION_USAGE} permission to ensure that only the
+ * system can launch this activity. The system will not launch
+ * activities that are not properly protected.
+ *
+ * <p>
+ * Input: {@code android.intent.extra.PERMISSION_NAME} specifies the permission
+ * for which the launched UI would be targeted.
+ * </p>
+ * <p>
+ * Output: Nothing.
+ * </p>
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ @RequiresPermission(android.Manifest.permission.START_VIEW_PERMISSION_USAGE)
+ public static final String ACTION_VIEW_PERMISSION_USAGE =
+ "android.intent.action.VIEW_PERMISSION_USAGE";
+
+ /**
* Activity action: Launch UI to manage a default app.
* <p>
* Input: {@link #EXTRA_ROLE_NAME} specifies the role of the default app which will be managed
@@ -2445,6 +2470,18 @@
public static final String ACTION_PACKAGE_ENABLE_ROLLBACK =
"android.intent.action.PACKAGE_ENABLE_ROLLBACK";
/**
+ * Broadcast Action: Sent to the system rollback manager when the rollback for a certain
+ * package needs to be cancelled.
+ *
+ * <p class="note">This intent is sent by PackageManagerService to notify RollbackManager
+ * that enabling a specific rollback has timed out.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_CANCEL_ENABLE_ROLLBACK =
+ "android.intent.action.CANCEL_ENABLE_ROLLBACK";
+ /**
* Broadcast Action: A rollback has been committed.
*
* <p class="note">This is a protected intent that can only be sent
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index d2f0fb3..89eabc2 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1278,7 +1278,7 @@
public int mode = MODE_INVALID;
/** {@hide} */
@UnsupportedAppUsage
- public int installFlags;
+ public int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
/** {@hide} */
public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
/** {@hide} */
@@ -1318,6 +1318,8 @@
public boolean isMultiPackage;
/** {@hide} */
public boolean isStaged;
+ /** {@hide} */
+ public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
/**
* Construct parameters for a new package install session.
@@ -1350,6 +1352,7 @@
installerPackageName = source.readString();
isMultiPackage = source.readBoolean();
isStaged = source.readBoolean();
+ requiredInstalledVersionCode = source.readLong();
}
/** {@hide} */
@@ -1372,6 +1375,7 @@
ret.installerPackageName = installerPackageName;
ret.isMultiPackage = isMultiPackage;
ret.isStaged = isStaged;
+ ret.requiredInstalledVersionCode = requiredInstalledVersionCode;
return ret;
}
@@ -1509,10 +1513,9 @@
* state of the permission can be determined only at install time and cannot be
* changed on updated or at a later point via the package manager APIs.
*
- * <p>The whitelisted non-immutably restricted permissions would be added to
- * the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER installer whitelist}
- * while the immutably restricted permissions would be added to the {@link
- * PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM system whitelist}
+ * <p>Initially, all restricted permissions are whitelisted but you can change
+ * which ones are whitelisted by calling this method or the corresponding ones
+ * on the {@link PackageManager}.
*
* @see PackageManager#addWhitelistedRestrictedPermission(String, String, int)
* @see PackageManager#removeWhitelistedRestrictedPermission(String, String, int)
@@ -1520,12 +1523,11 @@
public void setWhitelistedRestrictedPermissions(@Nullable Set<String> permissions) {
if (permissions == RESTRICTED_PERMISSIONS_ALL) {
installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
- }
- if (permissions != null) {
- this.whitelistedRestrictedPermissions = new ArrayList<>(permissions);
+ whitelistedRestrictedPermissions = null;
} else {
installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
- this.whitelistedRestrictedPermissions = null;
+ whitelistedRestrictedPermissions = (permissions != null)
+ ? new ArrayList<>(permissions) : null;
}
}
@@ -1567,6 +1569,19 @@
}
}
+ /**
+ * Require the given version of the package be installed.
+ * The install will only be allowed if the existing version code of
+ * the package installed on the device matches the given version code.
+ * Use {@link * PackageManager#VERSION_CODE_HIGHEST} to allow
+ * installation regardless of the currently installed package version.
+ *
+ * @hide
+ */
+ public void setRequiredInstalledVersionCode(long versionCode) {
+ requiredInstalledVersionCode = versionCode;
+ }
+
/** {@hide} */
public void setInstallFlagsForcePermissionPrompt() {
installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT;
@@ -1708,6 +1723,7 @@
pw.printPair("installerPackageName", installerPackageName);
pw.printPair("isMultiPackage", isMultiPackage);
pw.printPair("isStaged", isStaged);
+ pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
pw.println();
}
@@ -1736,6 +1752,7 @@
dest.writeString(installerPackageName);
dest.writeBoolean(isMultiPackage);
dest.writeBoolean(isStaged);
+ dest.writeLong(requiredInstalledVersionCode);
}
public static final Parcelable.Creator<SessionParams>
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 33c0bb9..bdab1e2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -86,11 +86,6 @@
/** {@hide} */
public static final boolean APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE = true;
- /** {@hide} */
- @TestApi
- // STOPSHIP: Remove this once we get a Play prebuilt.
- public static boolean RESTRICTED_PERMISSIONS_ENABLED = false;
-
/**
* This exception is thrown when a given package, application, or component
* name cannot be found.
@@ -730,6 +725,7 @@
INSTALL_APEX,
INSTALL_ENABLE_ROLLBACK,
INSTALL_ALLOW_DOWNGRADE,
+ INSTALL_STAGED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface InstallFlags {}
@@ -899,6 +895,14 @@
*/
public static final int INSTALL_ALLOW_DOWNGRADE = 0x00100000;
+ /**
+ * Flag parameter for {@link #installPackage} to indicate that this package
+ * is being installed as part of a staged install.
+ *
+ * @hide
+ */
+ public static final int INSTALL_STAGED = 0x00200000;
+
/** @hide */
@IntDef(flag = true, prefix = { "DONT_KILL_APP" }, value = {
DONT_KILL_APP
@@ -1423,6 +1427,14 @@
*/
public static final int INSTALL_FAILED_MULTIPACKAGE_INCONSISTENCY = -120;
+ /**
+ * Installation failed return code: the required installed version code
+ * does not match the currently installed package version code.
+ *
+ * @hide
+ */
+ public static final int INSTALL_FAILED_WRONG_INSTALLED_VERSION = -121;
+
/** @hide */
@IntDef(flag = true, prefix = { "DELETE_" }, value = {
DELETE_KEEP_DATA,
@@ -6918,6 +6930,7 @@
case INSTALL_FAILED_BAD_DEX_METADATA: return "INSTALL_FAILED_BAD_DEX_METADATA";
case INSTALL_FAILED_MISSING_SPLIT: return "INSTALL_FAILED_MISSING_SPLIT";
case INSTALL_FAILED_BAD_SIGNATURE: return "INSTALL_FAILED_BAD_SIGNATURE";
+ case INSTALL_FAILED_WRONG_INSTALLED_VERSION: return "INSTALL_FAILED_WRONG_INSTALLED_VERSION";
default: return Integer.toString(status);
}
}
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index e14d7e8..5a69e6b 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -174,6 +174,22 @@
}
/**
+ * Provider for default dialer
+ */
+ public interface DefaultDialerProvider {
+
+ /**
+ * Get the package name of the default dialer.
+ *
+ * @param userId the user id
+ *
+ * @return the package name of the default dialer, or {@code null} if none
+ */
+ @Nullable
+ String getDefaultDialer(@UserIdInt int userId);
+ }
+
+ /**
* Provider for default home
*/
public interface DefaultHomeProvider {
@@ -230,14 +246,6 @@
public abstract void setSyncAdapterPackagesprovider(SyncAdapterPackagesProvider provider);
/**
- * Called when the package for the default dialer changed
- *
- * @param packageName the new dialer package
- * @param userId user for which the change was made
- */
- public void onDefaultDialerAppChanged(String packageName, int userId) {}
-
- /**
* Called when the package for the default SMS handler changed
*
* @param packageName the new sms package
@@ -932,6 +940,13 @@
public abstract void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider);
/**
+ * Sets the default dialer provider.
+ *
+ * @param provider the provider
+ */
+ public abstract void setDefaultDialerProvider(@NonNull DefaultDialerProvider provider);
+
+ /**
* Sets the default home provider.
*
* @param provider the provider
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 1784d8a..7522bfb 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -238,24 +238,6 @@
CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
}
- // STOPSHIP(b/112545973): remove once feature enabled by default
- private static final Set<String> FORCE_AUDIO_PACKAGES;
- private static final Set<String> FORCE_VIDEO_PACKAGES;
- private static final Set<String> FORCE_IMAGES_PACKAGES;
- static {
- FORCE_AUDIO_PACKAGES = parsePackageList(
- SystemProperties.get(StorageManager.PROP_FORCE_AUDIO));
- FORCE_VIDEO_PACKAGES = parsePackageList(
- SystemProperties.get(StorageManager.PROP_FORCE_VIDEO));
- FORCE_IMAGES_PACKAGES = parsePackageList(
- SystemProperties.get(StorageManager.PROP_FORCE_IMAGES));
- }
-
- private static Set<String> parsePackageList(String pkgs) {
- if (TextUtils.isEmpty(pkgs)) return Collections.emptySet();
- return new ArraySet<String>(Arrays.asList(pkgs.split(",")));
- }
-
private static final boolean LOG_UNSAFE_BROADCASTS = false;
/**
@@ -2554,34 +2536,6 @@
adjustPackageToBeUnresizeableAndUnpipable(pkg);
}
- // If the storage model feature flag is disabled, we need to fiddle
- // around with permission definitions to return us to pre-Q behavior.
- // STOPSHIP(b/112545973): remove once feature enabled by default
- if (!StorageManager.hasIsolatedStorage()) {
- if ("android".equals(pkg.packageName)) {
- final ArraySet<String> newPermissions = new ArraySet<>();
- newPermissions.add(android.Manifest.permission.ACCESS_MEDIA_LOCATION);
- newPermissions.add(android.Manifest.permission.WRITE_OBB);
-
- for (int i = pkg.permissions.size() - 1; i >= 0; i--) {
- final Permission p = pkg.permissions.get(i);
- if (newPermissions.contains(p.info.name)) {
- pkg.permissions.remove(i);
- }
- }
- }
- } else {
- if (FORCE_AUDIO_PACKAGES.contains(pkg.packageName)) {
- pkg.requestedPermissions.add(android.Manifest.permission.READ_EXTERNAL_STORAGE);
- }
- if (FORCE_VIDEO_PACKAGES.contains(pkg.packageName)) {
- pkg.requestedPermissions.add(android.Manifest.permission.READ_EXTERNAL_STORAGE);
- }
- if (FORCE_IMAGES_PACKAGES.contains(pkg.packageName)) {
- pkg.requestedPermissions.add(android.Manifest.permission.READ_EXTERNAL_STORAGE);
- }
- }
-
return pkg;
}
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 14340fe..dd5c6a5 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -316,6 +316,7 @@
* value of {@link android.R.attr#permissionFlags}.
* @hide
*/
+ @TestApi
@SystemApi
public static final int FLAG_REMOVED = 1<<1;
@@ -360,8 +361,11 @@
/** @hide */
@IntDef(flag = true, prefix = { "FLAG_" }, value = {
FLAG_COSTS_MONEY,
- FLAG_INSTALLED,
- FLAG_REMOVED
+ FLAG_REMOVED,
+ FLAG_HARD_RESTRICTED,
+ FLAG_SOFT_RESTRICTED,
+ FLAG_IMMUTABLY_RESTRICTED,
+ FLAG_INSTALLED
})
@Retention(RetentionPolicy.SOURCE)
public @interface Flags {}
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 8b02cae..861ae7b 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -55,6 +55,7 @@
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.DisplayMetrics;
+import android.util.Slog;
import android.util.proto.ProtoInputStream;
import android.util.proto.ProtoOutputStream;
import android.util.proto.WireTypeMismatchException;
@@ -70,6 +71,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.IllformedLocaleException;
import java.util.List;
import java.util.Locale;
@@ -87,6 +89,8 @@
/** @hide */
public static final Configuration EMPTY = new Configuration();
+ private static final String TAG = "Configuration";
+
/**
* Current user preference for the scaling factor for fonts, relative
* to the base density scaling.
@@ -1186,6 +1190,7 @@
String language = "";
String country = "";
String variant = "";
+ String script = "";
try {
while (protoInputStream.nextField()
!= ProtoInputStream.NO_MORE_FIELDS) {
@@ -1200,6 +1205,9 @@
case (int) LocaleProto.VARIANT:
variant = protoInputStream.readString(LocaleProto.VARIANT);
break;
+ case (int) LocaleProto.SCRIPT:
+ script = protoInputStream.readString(LocaleProto.SCRIPT);
+ break;
}
}
} catch (WireTypeMismatchException wtme) {
@@ -1207,7 +1215,19 @@
throw wtme;
} finally {
protoInputStream.end(localeToken);
- list.add(new Locale(language, country, variant));
+ try {
+ final Locale locale = new Locale.Builder()
+ .setLanguage(language)
+ .setRegion(country)
+ .setVariant(variant)
+ .setScript(script)
+ .build();
+ list.add(locale);
+ } catch (IllformedLocaleException e) {
+ Slog.e(TAG, "readFromProto error building locale with: "
+ + "language-" + language + ";country-" + country
+ + ";variant-" + variant + ";script-" + script);
+ }
}
break;
case (int) SCREEN_LAYOUT:
diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java
index d54a6fe..9a10a0c 100644
--- a/core/java/android/content/rollback/RollbackManager.java
+++ b/core/java/android/content/rollback/RollbackManager.java
@@ -40,7 +40,7 @@
* used to initiate rollback of those packages for a limited time period after
* upgrade.
*
- * @see PackageInstaller.SessionParams#setEnableRollback()
+ * @see PackageInstaller.SessionParams#setEnableRollback(boolean)
* @hide
*/
@SystemApi @TestApi
@@ -52,7 +52,7 @@
/**
* Lifetime duration of rollback packages in millis. A rollback will be available for
* at most that duration of time after a package is installed with
- * {@link PackageInstaller.SessionParams#setEnableRollback()}.
+ * {@link PackageInstaller.SessionParams#setEnableRollback(boolean)}.
*
* <p>If flag value is negative, the default value will be assigned.
*
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index b44458a..cc5d3b1 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -419,26 +419,36 @@
Preconditions.checkNotNull(cr);
Preconditions.checkNotNull(notifyUris);
- setNotificationUris(cr, notifyUris, cr.getUserId());
+ setNotificationUris(cr, notifyUris, cr.getUserId(), true);
}
- /** @hide - set the notification uri but with an observer for a particular user's view */
- public void setNotificationUris(ContentResolver cr, List<Uri> notifyUris, int userHandle) {
+ /**
+ * Set the notification uri but with an observer for a particular user's view. Also allows
+ * disabling the use of a self observer, which is sensible if either
+ * a) the cursor's owner calls {@link #onChange(boolean)} whenever the content changes, or
+ * b) the cursor is known not to have any content observers.
+ * @hide
+ */
+ public void setNotificationUris(ContentResolver cr, List<Uri> notifyUris, int userHandle,
+ boolean registerSelfObserver) {
synchronized (mSelfObserverLock) {
mNotifyUris = notifyUris;
mNotifyUri = mNotifyUris.get(0);
mContentResolver = cr;
if (mSelfObserver != null) {
mContentResolver.unregisterContentObserver(mSelfObserver);
+ mSelfObserverRegistered = false;
}
- mSelfObserver = new SelfContentObserver(this);
- final int size = mNotifyUris.size();
- for (int i = 0; i < size; ++i) {
- final Uri notifyUri = mNotifyUris.get(i);
- mContentResolver.registerContentObserver(
- notifyUri, true, mSelfObserver, userHandle);
+ if (registerSelfObserver) {
+ mSelfObserver = new SelfContentObserver(this);
+ final int size = mNotifyUris.size();
+ for (int i = 0; i < size; ++i) {
+ final Uri notifyUri = mNotifyUris.get(i);
+ mContentResolver.registerContentObserver(
+ notifyUri, true, mSelfObserver, userHandle);
+ }
+ mSelfObserverRegistered = true;
}
- mSelfObserverRegistered = true;
}
}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 4aa6fab..099ae29 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -364,6 +364,8 @@
* count steps if it is not activated. This sensor is ideal for fitness tracking applications.
* It is defined as an {@link Sensor#REPORTING_MODE_ON_CHANGE} sensor.
* <p>
+ * This sensor requires permission {@code android.permission.ACTIVITY_RECOGNITION}.
+ * <p>
* See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
*/
public static final int TYPE_STEP_COUNTER = 19;
@@ -382,6 +384,8 @@
* gyroscope. This sensor uses lower power than the other rotation vectors, because it doesn't
* use the gyroscope. However, it is more noisy and will work best outdoors.
* <p>
+ * This sensor requires permission {@code android.permission.ACTIVITY_RECOGNITION}.
+ * <p>
* See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
*/
public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20;
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index d7db1f5..226b8e5 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -36,6 +36,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
* A class for describing camera output, which contains a {@link Surface} and its specific
@@ -692,7 +693,8 @@
mIsShared != other.mIsShared ||
mConfiguredFormat != other.mConfiguredFormat ||
mConfiguredDataspace != other.mConfiguredDataspace ||
- mConfiguredGenerationId != other.mConfiguredGenerationId)
+ mConfiguredGenerationId != other.mConfiguredGenerationId ||
+ !Objects.equals(mPhysicalCameraId, other.mPhysicalCameraId))
return false;
int minLen = Math.min(mSurfaces.size(), other.mSurfaces.size());
diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java
index ce71db6..90d312e 100644
--- a/core/java/android/hardware/display/ColorDisplayManager.java
+++ b/core/java/android/hardware/display/ColorDisplayManager.java
@@ -162,6 +162,20 @@
*/
public static final int COLOR_MODE_AUTOMATIC = 3;
+ /**
+ * Display color mode range reserved for vendor customizations by the RenderIntent definition in
+ * hardware/interfaces/graphics/common/1.1/types.hal. These are NOT directly related to (but ARE
+ * mutually exclusive with) the {@link ColorMode} constants, but ARE directly related (and ARE
+ * mutually exclusive with) the DISPLAY_COLOR_* constants in DisplayTransformManager.
+ *
+ * @hide
+ */
+ public static final int VENDOR_COLOR_MODE_RANGE_MIN = 256; // 0x100
+ /**
+ * @hide
+ */
+ public static final int VENDOR_COLOR_MODE_RANGE_MAX = 511; // 0x1ff
+
private final ColorDisplayManagerInternal mManager;
private MetricsLogger mMetricsLogger;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 0e10de8..a69ca99 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3449,6 +3449,10 @@
final NetworkCallback callback;
synchronized (sCallbacks) {
callback = sCallbacks.get(request);
+ if (message.what == CALLBACK_UNAVAIL) {
+ sCallbacks.remove(request);
+ callback.networkRequest = ALREADY_UNREGISTERED;
+ }
}
if (DBG) {
Log.d(TAG, getCallbackName(message.what) + " for network " + network);
@@ -3995,8 +3999,10 @@
synchronized (sCallbacks) {
Preconditions.checkArgument(networkCallback.networkRequest != null,
"NetworkCallback was not registered");
- Preconditions.checkArgument(networkCallback.networkRequest != ALREADY_UNREGISTERED,
- "NetworkCallback was already unregistered");
+ if (networkCallback.networkRequest == ALREADY_UNREGISTERED) {
+ Log.d(TAG, "NetworkCallback was already unregistered");
+ return;
+ }
for (Map.Entry<NetworkRequest, NetworkCallback> e : sCallbacks.entrySet()) {
if (e.getValue() == networkCallback) {
reqs.add(e.getKey());
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 1145d5b..83813da 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -19,11 +19,13 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -749,6 +751,7 @@
* @hide
*/
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
try {
@@ -771,6 +774,7 @@
* @hide
*/
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
try {
@@ -886,6 +890,7 @@
*/
@SystemApi
@NonNull
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
@NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
@@ -916,6 +921,7 @@
* @hide
*/
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel,
@PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
@@ -947,7 +953,8 @@
throw new IllegalArgumentException(sse);
} else if (sse.errorCode == OsConstants.EAGAIN) {
throw new IllegalStateException(sse);
- } else if (sse.errorCode == OsConstants.EOPNOTSUPP) {
+ } else if (sse.errorCode == OsConstants.EOPNOTSUPP
+ || sse.errorCode == OsConstants.EPROTONOSUPPORT) {
throw new UnsupportedOperationException(sse);
}
}
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index e519fdf..36111f2 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -21,9 +21,11 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -483,6 +485,7 @@
*/
@SystemApi
@NonNull
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public IpSecTransform buildTunnelModeTransform(
@NonNull InetAddress sourceAddress,
diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java
index 9d91620..46eddde 100644
--- a/core/java/android/net/SocketKeepalive.java
+++ b/core/java/android/net/SocketKeepalive.java
@@ -43,6 +43,10 @@
* To stop an existing keepalive, call {@link SocketKeepalive#stop}. The system will call
* {@link SocketKeepalive.Callback#onStopped} if the operation was successful or
* {@link SocketKeepalive.Callback#onError} if an error occurred.
+ *
+ * The device SHOULD support keepalive offload. If it does not, it MUST reply with
+ * {@link SocketKeepalive.Callback#onError} with {@code ERROR_UNSUPPORTED} to any keepalive offload
+ * request. If it does, it MUST support at least 3 concurrent keepalive slots per transport.
*/
public abstract class SocketKeepalive implements AutoCloseable {
static final String TAG = "SocketKeepalive";
diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java
index 2bd4378..e9c209c 100644
--- a/core/java/android/net/metrics/ApfProgramEvent.java
+++ b/core/java/android/net/metrics/ApfProgramEvent.java
@@ -176,7 +176,7 @@
out.writeInt(filteredRas);
out.writeInt(currentRas);
out.writeInt(programLength);
- out.writeInt(flags);
+ out.writeInt(this.flags);
}
/** @hide */
@@ -192,6 +192,18 @@
programLength, actualLifetime, lifetimeString, namesOf(flags));
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(ApfProgramEvent.class))) return false;
+ final ApfProgramEvent other = (ApfProgramEvent) obj;
+ return lifetime == other.lifetime
+ && actualLifetime == other.actualLifetime
+ && filteredRas == other.filteredRas
+ && currentRas == other.currentRas
+ && programLength == other.programLength
+ && flags == other.flags;
+ }
+
/** @hide */
public static final @android.annotation.NonNull Parcelable.Creator<ApfProgramEvent> CREATOR
= new Parcelable.Creator<ApfProgramEvent>() {
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index 6c3b7af..b963777 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -275,6 +275,22 @@
.toString();
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(ApfStats.class))) return false;
+ final ApfStats other = (ApfStats) obj;
+ return durationMs == other.durationMs
+ && receivedRas == other.receivedRas
+ && matchingRas == other.matchingRas
+ && droppedRas == other.droppedRas
+ && zeroLifetimeRas == other.zeroLifetimeRas
+ && parseErrors == other.parseErrors
+ && programUpdates == other.programUpdates
+ && programUpdatesAll == other.programUpdatesAll
+ && programUpdatesAllowingMulticast == other.programUpdatesAllowingMulticast
+ && maxProgramSize == other.maxProgramSize;
+ }
+
/** @hide */
public static final @android.annotation.NonNull Parcelable.Creator<ApfStats> CREATOR = new Parcelable.Creator<ApfStats>() {
public ApfStats createFromParcel(Parcel in) {
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index a3d0a20..2fed736 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -22,6 +22,7 @@
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
/**
* An event recorded when a DhcpClient state machine transitions to a new state.
@@ -101,6 +102,14 @@
return String.format("DhcpClientEvent(%s, %dms)", msg, durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(DhcpClientEvent.class))) return false;
+ final DhcpClientEvent other = (DhcpClientEvent) obj;
+ return TextUtils.equals(msg, other.msg)
+ && durationMs == other.durationMs;
+ }
+
/** @hide */
public static final @android.annotation.NonNull Parcelable.Creator<DhcpClientEvent> CREATOR
= new Parcelable.Creator<DhcpClientEvent>() {
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index 9d358d1..ba05c59 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -101,6 +101,14 @@
Decoder.constants.get(eventType), durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(IpManagerEvent.class))) return false;
+ final IpManagerEvent other = (IpManagerEvent) obj;
+ return eventType == other.eventType
+ && durationMs == other.durationMs;
+ }
+
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{IpManagerEvent.class},
diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java
index 80c8211..d4ba294 100644
--- a/core/java/android/net/metrics/IpReachabilityEvent.java
+++ b/core/java/android/net/metrics/IpReachabilityEvent.java
@@ -93,6 +93,13 @@
return String.format("IpReachabilityEvent(%s:%02x)", eventName, lo);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(IpReachabilityEvent.class))) return false;
+ final IpReachabilityEvent other = (IpReachabilityEvent) obj;
+ return eventType == other.eventType;
+ }
+
final static class Decoder {
static final SparseArray<String> constants =
MessageUtils.findMessageNames(new Class[]{IpReachabilityEvent.class},
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index bed914d..0c57ec6 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -121,6 +121,14 @@
Decoder.constants.get(eventType), durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(NetworkEvent.class))) return false;
+ final NetworkEvent other = (NetworkEvent) obj;
+ return eventType == other.eventType
+ && durationMs == other.durationMs;
+ }
+
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{NetworkEvent.class}, new String[]{"NETWORK_"});
diff --git a/core/java/android/net/metrics/RaEvent.java b/core/java/android/net/metrics/RaEvent.java
index b2f6585..3fd87c2 100644
--- a/core/java/android/net/metrics/RaEvent.java
+++ b/core/java/android/net/metrics/RaEvent.java
@@ -97,6 +97,18 @@
.toString();
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(RaEvent.class))) return false;
+ final RaEvent other = (RaEvent) obj;
+ return routerLifetime == other.routerLifetime
+ && prefixValidLifetime == other.prefixValidLifetime
+ && prefixPreferredLifetime == other.prefixPreferredLifetime
+ && routeInfoLifetime == other.routeInfoLifetime
+ && rdnssLifetime == other.rdnssLifetime
+ && dnsslLifetime == other.dnsslLifetime;
+ }
+
/** @hide */
public static final @android.annotation.NonNull Parcelable.Creator<RaEvent> CREATOR = new Parcelable.Creator<RaEvent>() {
public RaEvent createFromParcel(Parcel in) {
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index c9d7b1b..1aaa50d 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -170,6 +170,15 @@
getProbeName(probeType), returnCode, getValidationStage(probeType), durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(ValidationProbeEvent.class))) return false;
+ final ValidationProbeEvent other = (ValidationProbeEvent) obj;
+ return durationMs == other.durationMs
+ && probeType == other.probeType
+ && returnCode == other.returnCode;
+ }
+
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{ValidationProbeEvent.class},
diff --git a/core/java/android/net/util/KeepaliveUtils.java b/core/java/android/net/util/KeepaliveUtils.java
new file mode 100644
index 0000000..569fed1
--- /dev/null
+++ b/core/java/android/net/util/KeepaliveUtils.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.util;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.NetworkCapabilities;
+import android.text.TextUtils;
+import android.util.AndroidRuntimeException;
+
+import com.android.internal.R;
+
+/**
+ * Collection of utilities for socket keepalive offload.
+ *
+ * @hide
+ */
+public final class KeepaliveUtils {
+
+ public static final String TAG = "KeepaliveUtils";
+
+ // Minimum supported keepalive count per transport if the network supports keepalive.
+ public static final int MIN_SUPPORTED_KEEPALIVE_COUNT = 3;
+
+ public static class KeepaliveDeviceConfigurationException extends AndroidRuntimeException {
+ public KeepaliveDeviceConfigurationException(final String msg) {
+ super(msg);
+ }
+ }
+
+ /**
+ * Read supported keepalive count for each transport type from overlay resource. This should be
+ * used to create a local variable store of resource customization, and use it as the input for
+ * {@link getSupportedKeepalivesForNetworkCapabilities}.
+ *
+ * @param context The context to read resource from.
+ * @return An array of supported keepalive count for each transport type.
+ */
+ @NonNull
+ public static int[] getSupportedKeepalives(@NonNull Context context) {
+ String[] res = null;
+ try {
+ res = context.getResources().getStringArray(
+ R.array.config_networkSupportedKeepaliveCount);
+ } catch (Resources.NotFoundException unused) {
+ }
+ if (res == null) throw new KeepaliveDeviceConfigurationException("invalid resource");
+
+ final int[] ret = new int[NetworkCapabilities.MAX_TRANSPORT + 1];
+ for (final String row : res) {
+ if (TextUtils.isEmpty(row)) {
+ throw new KeepaliveDeviceConfigurationException("Empty string");
+ }
+ final String[] arr = row.split(",");
+ if (arr.length != 2) {
+ throw new KeepaliveDeviceConfigurationException("Invalid parameter length");
+ }
+
+ int transport;
+ int supported;
+ try {
+ transport = Integer.parseInt(arr[0]);
+ supported = Integer.parseInt(arr[1]);
+ } catch (NumberFormatException e) {
+ throw new KeepaliveDeviceConfigurationException("Invalid number format");
+ }
+
+ if (!NetworkCapabilities.isValidTransport(transport)) {
+ throw new KeepaliveDeviceConfigurationException("Invalid transport " + transport);
+ }
+
+ // Customized values should be either 0 to indicate the network doesn't support
+ // keepalive offload, or a positive value that is at least
+ // MIN_SUPPORTED_KEEPALIVE_COUNT if supported.
+ if (supported != 0 && supported < MIN_SUPPORTED_KEEPALIVE_COUNT) {
+ throw new KeepaliveDeviceConfigurationException(
+ "Invalid supported count " + supported + " for "
+ + NetworkCapabilities.transportNameOf(transport));
+ }
+ ret[transport] = supported;
+ }
+ return ret;
+ }
+
+ /**
+ * Get supported keepalive count for the given {@link NetworkCapabilities}.
+ *
+ * @param supportedKeepalives An array of supported keepalive count for each transport type.
+ * @param nc The {@link NetworkCapabilities} of the network the socket keepalive is on.
+ *
+ * @return Supported keepalive count for the given {@link NetworkCapabilities}.
+ */
+ public static int getSupportedKeepalivesForNetworkCapabilities(
+ @NonNull int[] supportedKeepalives, @NonNull NetworkCapabilities nc) {
+ final int[] transports = nc.getTransportTypes();
+ if (transports.length == 0) return 0;
+ int supportedCount = supportedKeepalives[transports[0]];
+ // Iterate through transports and return minimum supported value.
+ for (final int transport : transports) {
+ if (supportedCount > supportedKeepalives[transport]) {
+ supportedCount = supportedKeepalives[transport];
+ }
+ }
+ return supportedCount;
+ }
+}
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 83e1980..3cdebac 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -26,12 +26,14 @@
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.Context;
+import android.util.Log;
import com.android.internal.util.Preconditions;
import libcore.io.IoUtils;
-import java.io.FileDescriptor;
+import java.io.File;
+import java.io.FileNotFoundException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
@@ -45,6 +47,9 @@
@TestApi
@SystemService(Context.BUGREPORT_SERVICE)
public final class BugreportManager {
+
+ private static final String TAG = "BugreportManager";
+
private final Context mContext;
private final IDumpstate mBinder;
@@ -149,16 +154,22 @@
Preconditions.checkNotNull(executor);
Preconditions.checkNotNull(callback);
+ if (screenshotFd == null) {
+ // Binder needs a valid File Descriptor to be passed
+ screenshotFd = ParcelFileDescriptor.open(new File("/dev/null"),
+ ParcelFileDescriptor.MODE_READ_ONLY);
+ }
DumpstateListener dsListener = new DumpstateListener(executor, callback);
// Note: mBinder can get callingUid from the binder transaction.
mBinder.startBugreport(-1 /* callingUid */,
mContext.getOpPackageName(),
bugreportFd.getFileDescriptor(),
- (screenshotFd != null
- ? screenshotFd.getFileDescriptor() : new FileDescriptor()),
+ screenshotFd.getFileDescriptor(),
params.getMode(), dsListener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (FileNotFoundException e) {
+ Log.wtf(TAG, "Not able to find /dev/null file: ", e);
} finally {
// We can close the file descriptors here because binder would have duped them.
IoUtils.closeQuietly(bugreportFd);
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 232869d..5039b31 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -71,6 +71,8 @@
"android.app.action.ANGLE_FOR_ANDROID_TOAST_MESSAGE";
private static final String INTENT_KEY_A4A_TOAST_MESSAGE = "A4A Toast Message";
private static final String GAME_DRIVER_WHITELIST_ALL = "*";
+ private static final int VULKAN_1_0 = 0x00400000;
+ private static final int VULKAN_1_1 = 0x00401000;
// GAME_DRIVER_ALL_APPS
// 0: Default (Invalid values fallback to default as well)
@@ -99,12 +101,19 @@
Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "chooseDriver");
if (!chooseDriver(context, coreSettings, pm, packageName)) {
setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME, SYSTEM_DRIVER_VERSION_CODE,
- SystemProperties.getLong(PROPERTY_GFX_DRIVER_BUILD_TIME, 0), packageName);
+ SystemProperties.getLong(PROPERTY_GFX_DRIVER_BUILD_TIME, 0), packageName,
+ getVulkanVersion(pm));
}
Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
}
/**
+ * Hint for GraphicsEnvironment that an activity is launching on the process.
+ * Then the app process is allowed to send stats to GpuStats module.
+ */
+ public static native void hintActivityLaunch();
+
+ /**
* Allow to query whether an application will use Game Driver.
*/
public static boolean shouldUseGameDriver(Context context, Bundle coreSettings,
@@ -200,6 +209,20 @@
return true;
}
+ private static int getVulkanVersion(PackageManager pm) {
+ // PackageManager doesn't have an API to retrieve the version of a specific feature, and we
+ // need to avoid retrieving all system features here and looping through them.
+ if (pm.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, VULKAN_1_1)) {
+ return VULKAN_1_1;
+ }
+
+ if (pm.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, VULKAN_1_0)) {
+ return VULKAN_1_0;
+ }
+
+ return 0;
+ }
+
/**
* Check whether application is debuggable
*/
@@ -601,28 +624,36 @@
return false;
}
- final String anglePkgName = getAnglePackageName(pm);
- if (anglePkgName.isEmpty()) {
- Log.e(TAG, "Failed to find ANGLE package.");
- return false;
- }
+ ApplicationInfo angleInfo = null;
- final ApplicationInfo angleInfo;
- String angleDebugPackage = getAngleDebugPackage(context, bundle);
- if (!angleDebugPackage.isEmpty()) {
- Log.i(TAG, "ANGLE debug package enabled: " + angleDebugPackage);
+ // If the developer has specified a debug package over ADB, attempt to find it
+ String anglePkgName = getAngleDebugPackage(context, bundle);
+ if (!anglePkgName.isEmpty()) {
+ Log.i(TAG, "ANGLE debug package enabled: " + anglePkgName);
try {
// Note the debug package does not have to be pre-installed
- angleInfo = pm.getApplicationInfo(angleDebugPackage, 0);
+ angleInfo = pm.getApplicationInfo(anglePkgName, 0);
} catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "ANGLE debug package '" + angleDebugPackage + "' not installed");
+ Log.w(TAG, "ANGLE debug package '" + anglePkgName + "' not installed");
return false;
}
- } else {
- try {
- angleInfo = pm.getApplicationInfo(anglePkgName, PackageManager.MATCH_SYSTEM_ONLY);
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "ANGLE package '" + anglePkgName + "' not installed");
+ }
+
+ // Otherwise, check to see if ANGLE is properly installed
+ if (angleInfo == null) {
+ anglePkgName = getAnglePackageName(pm);
+ if (!anglePkgName.isEmpty()) {
+ Log.i(TAG, "ANGLE package enabled: " + anglePkgName);
+ try {
+ // Production ANGLE libraries must be pre-installed as a system app
+ angleInfo = pm.getApplicationInfo(anglePkgName,
+ PackageManager.MATCH_SYSTEM_ONLY);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "ANGLE package '" + anglePkgName + "' not installed");
+ return false;
+ }
+ } else {
+ Log.e(TAG, "Failed to find ANGLE package.");
return false;
}
}
@@ -683,7 +714,7 @@
private boolean setupAndUseAngle(Context context, String packageName) {
// Need to make sure we are evaluating ANGLE usage for the correct circumstances
if (!setupAngle(context, null, context.getPackageManager(), packageName)) {
- Log.v(TAG, "Package '" + packageName + "' should use not ANGLE");
+ Log.v(TAG, "Package '" + packageName + "' should not use ANGLE");
return false;
}
@@ -791,7 +822,7 @@
// driver_build_time in the meta-data is in "L<Unix epoch timestamp>" format. e.g. L123456.
// Long.parseLong will throw if the meta-data "driver_build_time" is not set properly.
setGpuStats(driverPackageName, driverPackageInfo.versionName, driverAppInfo.longVersionCode,
- Long.parseLong(driverBuildTime.substring(1)), packageName);
+ Long.parseLong(driverBuildTime.substring(1)), packageName, 0);
return true;
}
@@ -815,7 +846,7 @@
private static native void setDebugLayersGLES(String layers);
private static native void setDriverPathAndSphalLibraries(String path, String sphalLibraries);
private static native void setGpuStats(String driverPackageName, String driverVersionName,
- long driverVersionCode, long driverBuildTime, String appPackageName);
+ long driverVersionCode, long driverBuildTime, String appPackageName, int vulkanVersion);
private static native void setAngleInfo(String path, String appPackage, String devOptIn,
FileDescriptor rulesFd, long rulesOffset, long rulesLength);
private static native boolean getShouldUseAngle(String packageName);
diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java
index 1f61a3c..ed8d3f7 100644
--- a/core/java/android/os/IncidentManager.java
+++ b/core/java/android/os/IncidentManager.java
@@ -576,7 +576,7 @@
}
final String id = uri.getQueryParameter(URI_PARAM_REPORT_ID);
- if (cls == null) {
+ if (id == null) {
throw new RuntimeException("Invalid URI: No "
+ URI_PARAM_REPORT_ID + " parameter. " + uri);
}
diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java
index 011810b..7782753 100644
--- a/core/java/android/os/LocaleList.java
+++ b/core/java/android/os/LocaleList.java
@@ -157,6 +157,7 @@
protoOutputStream.write(LocaleProto.LANGUAGE, locale.getLanguage());
protoOutputStream.write(LocaleProto.COUNTRY, locale.getCountry());
protoOutputStream.write(LocaleProto.VARIANT, locale.getVariant());
+ protoOutputStream.write(LocaleProto.SCRIPT, locale.getScript());
protoOutputStream.end(token);
}
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index b82b5ef..e50ab6c 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -511,7 +511,6 @@
* @param appDataDir null-ok the data directory of the app.
* @param invokeWith null-ok the command to invoke with.
* @param packageName null-ok the name of the package this process belongs to.
- * @param packagesForUid null-ok all the packages with the same uid as this process.
* @param useSystemGraphicsDriver whether the process uses system graphics driver.
*
* @param zygoteArgs Additional arguments to supply to the zygote process.
@@ -532,14 +531,12 @@
@Nullable String appDataDir,
@Nullable String invokeWith,
@Nullable String packageName,
- @Nullable String[] packagesForUid,
- @Nullable String sandboxId,
boolean useSystemGraphicsDriver,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
- packagesForUid, sandboxId, /*useUsapPool=*/ true,
+ /*useUsapPool=*/ true,
useSystemGraphicsDriver, zygoteArgs);
}
@@ -556,14 +553,12 @@
@Nullable String appDataDir,
@Nullable String invokeWith,
@Nullable String packageName,
- @Nullable String[] packagesForUid,
- @Nullable String sandboxId,
boolean useSystemGraphicsDriver,
@Nullable String[] zygoteArgs) {
return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
- packagesForUid, sandboxId, /*useUsapPool=*/ false,
+ /*useUsapPool=*/ false,
useSystemGraphicsDriver, zygoteArgs);
}
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 6478de2..2b170c2 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -306,7 +306,6 @@
* @param appDataDir null-ok the data directory of the app.
* @param invokeWith null-ok the command to invoke with.
* @param packageName null-ok the name of the package this process belongs to.
- * @param packagesForUid null-ok all the packages with the same uid as this process.
* @param zygoteArgs Additional arguments to supply to the zygote process.
* @param useSystemGraphicsDriver whether the process uses system graphics driver.
*
@@ -324,8 +323,6 @@
@Nullable String appDataDir,
@Nullable String invokeWith,
@Nullable String packageName,
- @Nullable String[] packagesForUid,
- @Nullable String sandboxId,
boolean useUsapPool,
boolean useSystemGraphicsDriver,
@Nullable String[] zygoteArgs) {
@@ -338,8 +335,7 @@
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
- packageName, packagesForUid, sandboxId,
- useUsapPool, useSystemGraphicsDriver, zygoteArgs);
+ packageName, useUsapPool, useSystemGraphicsDriver, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -532,7 +528,6 @@
* @param startChildZygote Start a sub-zygote. This creates a new zygote process
* that has its state cloned from this zygote process.
* @param packageName null-ok the name of the package this process belongs to.
- * @param packagesForUid null-ok all the packages with the same uid as this process.
* @param extraArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
* @throws ZygoteStartFailedEx if process start failed for any reason
@@ -550,8 +545,6 @@
@Nullable String invokeWith,
boolean startChildZygote,
@Nullable String packageName,
- @Nullable String[] packagesForUid,
- @Nullable String sandboxId,
boolean useUsapPool,
boolean useSystemGraphicsDriver,
@Nullable String[] extraArgs)
@@ -625,14 +618,6 @@
argsForZygote.add("--package-name=" + packageName);
}
- if (packagesForUid != null && packagesForUid.length > 0) {
- argsForZygote.add("--packages-for-uid=" + String.join(",", packagesForUid));
- }
-
- if (sandboxId != null) {
- argsForZygote.add("--sandbox-id=" + sandboxId);
- }
-
argsForZygote.add(processClass);
if (extraArgs != null) {
@@ -881,6 +866,7 @@
maybeSetApiBlacklistExemptions(primaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
+ maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState);
}
}
@@ -896,6 +882,7 @@
maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
+ maybeSetHiddenApiAccessStatslogSampleRate(secondaryZygoteState);
}
}
@@ -1147,7 +1134,6 @@
gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
true /* startChildZygote */, null /* packageName */,
- null /* packagesForUid */, null /* sandboxId */,
false /* useUsapPool */, false /*useSystemGraphicsDriver*/,
extraArgs);
} catch (ZygoteStartFailedEx ex) {
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 9db4111..92fecad 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -188,8 +188,6 @@
void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) = 78;
void runIdleMaintenance() = 79;
void abortIdleMaintenance() = 80;
- String translateAppToSystem(String path, int pid, int uid) = 81;
- String translateSystemToApp(String path, int pid, int uid) = 82;
void commitChanges() = 83;
boolean supportsCheckpoint() = 84;
void startCheckpoint(int numTries) = 85;
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index b9fc186..69c1295 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -155,13 +155,6 @@
public static final String PROP_ISOLATED_STORAGE_SNAPSHOT = "sys.isolated_storage_snapshot";
/** {@hide} */
- public static final String PROP_FORCE_AUDIO = "persist.fw.force_audio";
- /** {@hide} */
- public static final String PROP_FORCE_VIDEO = "persist.fw.force_video";
- /** {@hide} */
- public static final String PROP_FORCE_IMAGES = "persist.fw.force_images";
-
- /** {@hide} */
public static final String UUID_PRIVATE_INTERNAL = null;
/** {@hide} */
public static final String UUID_PRIMARY_PHYSICAL = "primary_physical";
@@ -255,6 +248,8 @@
public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE;
/** {@hide} */
public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE;
+ /** {@hide} */
+ public static final int FLAG_STORAGE_EXTERNAL = IInstalld.FLAG_STORAGE_EXTERNAL;
/** {@hide} */
public static final int FLAG_FOR_WRITE = 1 << 8;
@@ -291,9 +286,6 @@
public static final int ENCRYPTION_STATE_ERROR_CORRUPT =
IVold.ENCRYPTION_STATE_ERROR_CORRUPT;
- /** @hide Prefix used in sandboxIds for apps with sharedUserIds */
- public static final String SHARED_SANDBOX_PREFIX = "shared-";
-
private static volatile IStorageManager sStorageManager = null;
private final Context mContext;
@@ -1618,15 +1610,7 @@
* @hide
*/
public File translateAppToSystem(File file, int pid, int uid) {
- // We can only translate absolute paths
- if (!file.isAbsolute()) return file;
-
- try {
- return new File(mStorageManager.translateAppToSystem(file.getAbsolutePath(),
- pid, uid));
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return file;
}
/**
@@ -1636,15 +1620,7 @@
* @hide
*/
public File translateSystemToApp(File file, int pid, int uid) {
- // We can only translate absolute paths
- if (!file.isAbsolute()) return file;
-
- try {
- return new File(mStorageManager.translateSystemToApp(file.getAbsolutePath(),
- pid, uid));
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return file;
}
/**
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index f1c3138..942bf94 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -16,8 +16,6 @@
package android.os.storage;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.os.IVold;
/**
@@ -85,30 +83,6 @@
public abstract int getExternalStorageMountMode(int uid, String packageName);
/**
- * Create storage sandbox for the given package.
- *
- * <p> This will involve calling into vold to setup appropriate bind mounts.
- *
- * @param packageName The package for which the sandbox needs to be created.
- * @param appId The appId for the given package.
- * @param sharedUserId The sharedUserId for given package if it specified
- * {@code android:sharedUserId} in the manifest, otherwise {@code null}
- * @param userId The userId in which the sandbox needs to be created.
- */
- public abstract void prepareSandboxForApp(@NonNull String packageName, int appId,
- @Nullable String sharedUserId, int userId);
-
- /**
- * Delete storage sandbox for the given package.
- *
- * @param packageName The package for which the sandbox needs to be destroyed.
- * @param sharedUserId The sharedUserId if specified by the package.
- * @param userId The userId in which the sandbox needs to be destroyed.
- */
- public abstract void destroySandboxForApp(@NonNull String packageName,
- @Nullable String sharedUserId, int userId);
-
- /**
* A listener for reset events in the StorageManagerService.
*/
public interface ResetListener {
@@ -127,9 +101,4 @@
* @param listener The listener that will be notified on reset events.
*/
public abstract void addResetListener(ResetListener listener);
-
- /**
- * Return the sandboxId for the given package on external storage.
- */
- public abstract String getSandboxId(String packageName);
}
diff --git a/core/java/android/os/storage/VolumeRecord.java b/core/java/android/os/storage/VolumeRecord.java
index b6ee261..1a794eb 100644
--- a/core/java/android/os/storage/VolumeRecord.java
+++ b/core/java/android/os/storage/VolumeRecord.java
@@ -25,6 +25,7 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
+import java.util.Locale;
import java.util.Objects;
/**
@@ -45,6 +46,7 @@
public String nickname;
public int userFlags;
public long createdMillis;
+ public long lastSeenMillis;
public long lastTrimMillis;
public long lastBenchMillis;
@@ -61,6 +63,7 @@
nickname = parcel.readString();
userFlags = parcel.readInt();
createdMillis = parcel.readLong();
+ lastSeenMillis = parcel.readLong();
lastTrimMillis = parcel.readLong();
lastBenchMillis = parcel.readLong();
}
@@ -73,6 +76,10 @@
return fsUuid;
}
+ public String getNormalizedFsUuid() {
+ return fsUuid != null ? fsUuid.toLowerCase(Locale.US) : null;
+ }
+
public String getNickname() {
return nickname;
}
@@ -97,6 +104,7 @@
DebugUtils.flagsToString(VolumeRecord.class, "USER_FLAG_", userFlags));
pw.println();
pw.printPair("createdMillis", TimeUtils.formatForLogging(createdMillis));
+ pw.printPair("lastSeenMillis", TimeUtils.formatForLogging(lastSeenMillis));
pw.printPair("lastTrimMillis", TimeUtils.formatForLogging(lastTrimMillis));
pw.printPair("lastBenchMillis", TimeUtils.formatForLogging(lastBenchMillis));
pw.decreaseIndent();
@@ -155,6 +163,7 @@
parcel.writeString(nickname);
parcel.writeInt(userFlags);
parcel.writeLong(createdMillis);
+ parcel.writeLong(lastSeenMillis);
parcel.writeLong(lastTrimMillis);
parcel.writeLong(lastBenchMillis);
}
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index fa244e4..2f68eb4 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -187,6 +187,10 @@
* {@link android.database.ContentObserver} for this URL in the primary profile will be
* notified when there is a change in the managed profile calendar provider.
*
+ * <p>Throw UnsupportedOperationException if another profile doesn't exist or is disabled, or
+ * if the calling package is not whitelisted to access cross-profile calendar, or if the
+ * feature has been disabled by the user in Settings.
+ *
* @see Events#ENTERPRISE_CONTENT_URI
* @see Calendars#ENTERPRISE_CONTENT_URI
* @see Instances#ENTERPRISE_CONTENT_URI
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 774d4ae..9a11104 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -263,6 +263,7 @@
* Namespace for TextClassifier related features.
*
* @hide
+ * @see android.provider.Settings.Global.TEXT_CLASSIFIER_CONSTANTS
*/
@SystemApi
public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier";
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index c50d003..aa774a6 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -46,6 +46,7 @@
import android.graphics.Point;
import android.graphics.PostProcessor;
import android.media.ExifInterface;
+import android.media.MediaFile;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -1724,18 +1725,25 @@
@Deprecated
public static final String insertImage(ContentResolver cr, String imagePath,
String name, String description) throws FileNotFoundException {
- // Check if file exists with a FileInputStream
- FileInputStream stream = new FileInputStream(imagePath);
- try {
- Bitmap bm = BitmapFactory.decodeFile(imagePath);
- String ret = insertImage(cr, bm, name, description);
- bm.recycle();
- return ret;
- } finally {
- try {
- stream.close();
- } catch (IOException e) {
+ final File file = new File(imagePath);
+ final String mimeType = MediaFile.getMimeTypeForFile(imagePath);
+
+ if (TextUtils.isEmpty(name)) name = "Image";
+ final PendingParams params = new PendingParams(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI, name, mimeType);
+
+ final Context context = AppGlobals.getInitialApplication();
+ final Uri pendingUri = createPending(context, params);
+ try (PendingSession session = openPending(context, pendingUri)) {
+ try (InputStream in = new FileInputStream(file);
+ OutputStream out = session.openOutputStream()) {
+ FileUtils.copy(in, out);
}
+ return session.publish().toString();
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to insert image", e);
+ context.getContentResolver().delete(pendingUri, null, null);
+ return null;
}
}
@@ -1755,45 +1763,22 @@
@Deprecated
public static final String insertImage(ContentResolver cr, Bitmap source,
String title, String description) {
- ContentValues values = new ContentValues();
- values.put(Images.Media.DISPLAY_NAME, title);
- values.put(Images.Media.DESCRIPTION, description);
- values.put(Images.Media.MIME_TYPE, "image/jpeg");
+ if (TextUtils.isEmpty(title)) title = "Image";
+ final PendingParams params = new PendingParams(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI, title, "image/jpeg");
- Uri url = null;
- String stringUrl = null; /* value to be returned */
-
- try {
- url = cr.insert(getContentUri(VOLUME_EXTERNAL_PRIMARY), values);
-
- if (source != null) {
- try (OutputStream out = new ParcelFileDescriptor.AutoCloseOutputStream(
- cr.openFile(url, "w", null))) {
- source.compress(Bitmap.CompressFormat.JPEG, 50, out);
- }
-
- long id = ContentUris.parseId(url);
- // Block until we've generated common thumbnails
- Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MINI_KIND, null);
- Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MICRO_KIND, null);
- } else {
- Log.e(TAG, "Failed to create thumbnail, removing original");
- cr.delete(url, null, null);
- url = null;
+ final Context context = AppGlobals.getInitialApplication();
+ final Uri pendingUri = createPending(context, params);
+ try (PendingSession session = openPending(context, pendingUri)) {
+ try (OutputStream out = session.openOutputStream()) {
+ source.compress(Bitmap.CompressFormat.JPEG, 90, out);
}
+ return session.publish().toString();
} catch (Exception e) {
- Log.e(TAG, "Failed to insert image", e);
- if (url != null) {
- cr.delete(url, null, null);
- url = null;
- }
+ Log.w(TAG, "Failed to insert image", e);
+ context.getContentResolver().delete(pendingUri, null, null);
+ return null;
}
-
- if (url != null) {
- stringUrl = url.toString();
- }
-
- return stringUrl;
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8231a92..185d4a2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3455,10 +3455,25 @@
*/
public static final String DISPLAY_COLOR_MODE = "display_color_mode";
- private static final Validator DISPLAY_COLOR_MODE_VALIDATOR =
- new SettingsValidators.InclusiveIntegerRangeValidator(
- ColorDisplayManager.COLOR_MODE_NATURAL,
- ColorDisplayManager.COLOR_MODE_AUTOMATIC);
+ private static final Validator DISPLAY_COLOR_MODE_VALIDATOR = new Validator() {
+ @Override
+ public boolean validate(@Nullable String value) {
+ // Assume the actual validation that this device can properly handle this kind of
+ // color mode further down in ColorDisplayManager / ColorDisplayService.
+ try {
+ final int setting = Integer.parseInt(value);
+ final boolean isInFrameworkRange =
+ setting >= ColorDisplayManager.COLOR_MODE_NATURAL
+ && setting <= ColorDisplayManager.COLOR_MODE_AUTOMATIC;
+ final boolean isInVendorRange =
+ setting >= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN
+ && setting <= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MAX;
+ return isInFrameworkRange || isInVendorRange;
+ } catch (NumberFormatException | NullPointerException e) {
+ return false;
+ }
+ }
+ };
/**
* The user selected peak refresh rate in frames per second.
@@ -6484,6 +6499,28 @@
new SettingsValidators.ComponentNameListValidator(":");
/**
+ * Whether the Global Actions Panel is enabled.
+ * @hide
+ */
+ public static final String GLOBAL_ACTIONS_PANEL_ENABLED = "global_actions_panel_enabled";
+
+ private static final Validator GLOBAL_ACTIONS_PANEL_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
+ /**
+ * Whether the Global Actions Panel can be toggled on or off in Settings.
+ * @hide
+ */
+ public static final String GLOBAL_ACTIONS_PANEL_AVAILABLE =
+ "global_actions_panel_available";
+
+ /**
+ * Enables debug mode for the Global Actions Panel.
+ * @hide
+ */
+ public static final String GLOBAL_ACTIONS_PANEL_DEBUG_ENABLED =
+ "global_actions_panel_debug_enabled";
+
+ /**
* Whether the hush gesture has ever been used
* @hide
*/
@@ -7762,6 +7799,9 @@
*/
public static final String UI_NIGHT_MODE = "ui_night_mode";
+ private static final Validator UI_NIGHT_MODE_VALIDATOR =
+ new SettingsValidators.InclusiveIntegerRangeValidator(0, 2);
+
/**
* Whether screensavers are enabled.
* @hide
@@ -8240,6 +8280,16 @@
BOOLEAN_VALIDATOR;
/**
+ * Whether or not the face unlock education screen has been shown to the user.
+ * @hide
+ */
+ public static final String FACE_UNLOCK_EDUCATION_INFO_DISPLAYED =
+ "face_unlock_education_info_displayed";
+
+ private static final Validator FACE_UNLOCK_EDUCATION_INFO_DISPLAYED_VALIDATOR =
+ BOOLEAN_VALIDATOR;
+
+ /**
* Whether or not debugging is enabled.
* @hide
*/
@@ -8908,6 +8958,7 @@
ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS,
NOTIFICATION_NEW_INTERRUPTION_MODEL,
TRUST_AGENTS_EXTEND_UNLOCK,
+ UI_NIGHT_MODE,
LOCK_SCREEN_WHEN_TRUST_LOST,
SKIP_GESTURE,
SILENCE_GESTURE,
@@ -8918,7 +8969,8 @@
SILENCE_NOTIFICATION_GESTURE_COUNT,
SILENCE_CALL_GESTURE_COUNT,
SILENCE_TIMER_GESTURE_COUNT,
- DARK_MODE_DIALOG_SEEN
+ DARK_MODE_DIALOG_SEEN,
+ GLOBAL_ACTIONS_PANEL_ENABLED
};
/**
@@ -9044,6 +9096,8 @@
VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR);
+ VALIDATORS.put(FACE_UNLOCK_EDUCATION_INFO_DISPLAYED,
+ FACE_UNLOCK_EDUCATION_INFO_DISPLAYED_VALIDATOR);
VALIDATORS.put(ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_ENABLED_VALIDATOR);
VALIDATORS.put(ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR);
@@ -9101,6 +9155,8 @@
VALIDATORS.put(SILENCE_NOTIFICATION_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
VALIDATORS.put(ODI_CAPTIONS_ENABLED, ODI_CAPTIONS_ENABLED_VALIDATOR);
VALIDATORS.put(DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(UI_NIGHT_MODE, UI_NIGHT_MODE_VALIDATOR);
+ VALIDATORS.put(GLOBAL_ACTIONS_PANEL_ENABLED, GLOBAL_ACTIONS_PANEL_ENABLED_VALIDATOR);
}
/**
@@ -9128,6 +9184,7 @@
CLONE_TO_MANAGED_PROFILE.add(ACCESSIBILITY_ENABLED);
CLONE_TO_MANAGED_PROFILE.add(ALLOW_MOCK_LOCATION);
CLONE_TO_MANAGED_PROFILE.add(ALLOWED_GEOLOCATION_ORIGINS);
+ CLONE_TO_MANAGED_PROFILE.add(CONTENT_CAPTURE_ENABLED);
CLONE_TO_MANAGED_PROFILE.add(ENABLED_ACCESSIBILITY_SERVICES);
CLONE_TO_MANAGED_PROFILE.add(LOCATION_CHANGER);
CLONE_TO_MANAGED_PROFILE.add(LOCATION_MODE);
@@ -12039,26 +12096,27 @@
* entity_list_default use ":" as delimiter for values. Ex:
*
* <pre>
- * smart_linkify_enabled (boolean)
- * system_textclassifier_enabled (boolean)
+ * classify_text_max_range_length (int)
+ * detect_language_from_text_enabled (boolean)
+ * entity_list_default (String[])
+ * entity_list_editable (String[])
+ * entity_list_not_editable (String[])
+ * generate_links_log_sample_rate (int)
+ * generate_links_max_text_length (int)
+ * in_app_conversation_action_types_default (String[])
+ * lang_id_context_settings (float[])
+ * lang_id_threshold_override (float)
+ * local_textclassifier_enabled (boolean)
* model_dark_launch_enabled (boolean)
- * smart_selection_enabled (boolean)
- * smart_text_share_enabled (boolean)
+ * notification_conversation_action_types_default (String[])
* smart_linkify_enabled (boolean)
* smart_select_animation_enabled (boolean)
+ * smart_selection_enabled (boolean)
+ * smart_text_share_enabled (boolean)
* suggest_selection_max_range_length (int)
- * classify_text_max_range_length (int)
- * generate_links_max_text_length (int)
- * generate_links_log_sample_rate (int)
- * entity_list_default (String[])
- * entity_list_not_editable (String[])
- * entity_list_editable (String[])
- * in_app_conversation_action_types_default (String[])
- * notification_conversation_action_types_default (String[])
- * lang_id_threshold_override (float)
+ * system_textclassifier_enabled (boolean)
* template_intent_factory_enabled (boolean)
* translate_in_classification_enabled (boolean)
- * detect_language_from_text_enabled (boolean)
* </pre>
*
* <p>
diff --git a/core/java/android/service/appprediction/AppPredictionService.java b/core/java/android/service/appprediction/AppPredictionService.java
index c1323bc..be20570 100644
--- a/core/java/android/service/appprediction/AppPredictionService.java
+++ b/core/java/android/service/appprediction/AppPredictionService.java
@@ -20,6 +20,7 @@
import android.annotation.CallSuper;
import android.annotation.MainThread;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.Service;
@@ -38,6 +39,7 @@
import android.os.RemoteException;
import android.service.appprediction.IPredictionService.Stub;
import android.util.ArrayMap;
+import android.util.Log;
import android.util.Slog;
import java.util.ArrayList;
@@ -45,7 +47,7 @@
import java.util.function.Consumer;
/**
- * TODO(b/111701043): Add java docs
+ * A service used to predict app and shortcut usage.
*
* @hide
*/
@@ -57,7 +59,9 @@
/**
* The {@link Intent} that must be declared as handled by the service.
- * TODO(b/111701043): Add any docs about permissions the service must hold
+ *
+ * <p>The service must also require the {@link android.permission#MANAGE_APP_PREDICTIONS}
+ * permission.
*
* @hide
*/
@@ -100,7 +104,7 @@
mHandler.sendMessage(
obtainMessage(AppPredictionService::onSortAppTargets,
AppPredictionService.this, sessionId, targets.getList(), null,
- new CallbackWrapper(callback)));
+ new CallbackWrapper(callback, null)));
}
@Override
@@ -144,8 +148,11 @@
@Override
@NonNull
public final IBinder onBind(@NonNull Intent intent) {
- // TODO(b/111701043): Verify that the action is valid
- return mInterface.asBinder();
+ if (SERVICE_INTERFACE.equals(intent.getAction())) {
+ return mInterface.asBinder();
+ }
+ Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+ return null;
}
/**
@@ -179,7 +186,6 @@
/**
* Called by the client app to request sorting of targets based on prediction rank.
- * TODO(b/111701043): Implement CancellationSignal so caller can cancel a long running request
*/
@MainThread
public abstract void onSortAppTargets(@NonNull AppPredictionSessionId sessionId,
@@ -196,7 +202,9 @@
final CallbackWrapper wrapper = findCallbackWrapper(callbacks, callback);
if (wrapper == null) {
- callbacks.add(new CallbackWrapper(callback));
+ callbacks.add(new CallbackWrapper(callback,
+ callbackWrapper ->
+ mHandler.post(() -> removeCallbackWrapper(callbacks, callbackWrapper))));
if (callbacks.size() == 1) {
onStartPredictionUpdates();
}
@@ -219,10 +227,18 @@
final CallbackWrapper wrapper = findCallbackWrapper(callbacks, callback);
if (wrapper != null) {
- callbacks.remove(wrapper);
- if (callbacks.isEmpty()) {
- onStopPredictionUpdates();
- }
+ removeCallbackWrapper(callbacks, wrapper);
+ }
+ }
+
+ private void removeCallbackWrapper(
+ ArrayList<CallbackWrapper> callbacks, CallbackWrapper wrapper) {
+ if (callbacks == null) {
+ return;
+ }
+ callbacks.remove(wrapper);
+ if (callbacks.isEmpty()) {
+ onStopPredictionUpdates();
}
}
@@ -243,7 +259,6 @@
/**
* Called by the client app to request target predictions. This method is only called if there
* are one or more prediction callbacks registered.
- * TODO(b/111701043): Add java docs
*
* @see #updatePredictions(AppPredictionSessionId, List)
*/
@@ -295,9 +310,12 @@
IBinder.DeathRecipient {
private IPredictionCallback mCallback;
+ private final Consumer<CallbackWrapper> mOnBinderDied;
- CallbackWrapper(IPredictionCallback callback) {
+ CallbackWrapper(IPredictionCallback callback,
+ @Nullable Consumer<CallbackWrapper> onBinderDied) {
mCallback = callback;
+ mOnBinderDied = onBinderDied;
try {
mCallback.asBinder().linkToDeath(this, 0);
} catch (RemoteException e) {
@@ -306,6 +324,10 @@
}
public boolean isCallback(@NonNull IPredictionCallback callback) {
+ if (mCallback == null) {
+ Slog.e(TAG, "Callback is null, likely the binder has died.");
+ return false;
+ }
return mCallback.equals(callback);
}
@@ -323,6 +345,9 @@
@Override
public void binderDied() {
mCallback = null;
+ if (mOnBinderDied != null) {
+ mOnBinderDied.accept(this);
+ }
}
}
}
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 66864c6..91f77ea 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -71,14 +71,6 @@
*/
public static final int FLAG_COMPATIBILITY_MODE_REQUEST = 0x2;
- // Private flags below start from the highest-significative bit (0x80000000)
- /**
- * Request was only triggered for augmented autofill.
- *
- * @hide
- */
- public static final int FLAG_AUGMENTED_AUTOFILL_REQUEST = 0x80000000;
-
/** @hide */
public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 656127a..87e369f 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -15,6 +15,9 @@
*/
package android.service.autofill.augmented;
+import static android.service.autofill.augmented.Helper.logResponse;
+import static android.util.TimeUtils.formatDuration;
+
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import android.annotation.CallSuper;
@@ -38,9 +41,7 @@
import android.service.autofill.augmented.PresentationParams.SystemPopupPresentationParams;
import android.util.Log;
import android.util.Pair;
-import android.util.Slog;
import android.util.SparseArray;
-import android.util.TimeUtils;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
@@ -48,6 +49,7 @@
import android.view.autofill.IAutofillWindowPresenter;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -84,6 +86,9 @@
private SparseArray<AutofillProxy> mAutofillProxies;
+ // Used for metrics / debug only
+ private ComponentName mServiceComponentName;
+
private final IAugmentedAutofillService mInterface = new IAugmentedAutofillService.Stub() {
@Override
@@ -125,6 +130,7 @@
/** @hide */
@Override
public final IBinder onBind(Intent intent) {
+ mServiceComponentName = intent.getComponent();
if (SERVICE_INTERFACE.equals(intent.getAction())) {
return mInterface.asBinder();
}
@@ -215,8 +221,9 @@
final CancellationSignal cancellationSignal = CancellationSignal.fromTransport(transport);
AutofillProxy proxy = mAutofillProxies.get(sessionId);
if (proxy == null) {
- proxy = new AutofillProxy(sessionId, client, taskId, componentName, focusedId,
- focusedValue, requestTime, callback, cancellationSignal);
+ proxy = new AutofillProxy(sessionId, client, taskId, mServiceComponentName,
+ componentName, focusedId, focusedValue, requestTime, callback,
+ cancellationSignal);
mAutofillProxies.put(sessionId, proxy);
} else {
// TODO(b/123099468): figure out if it's ok to reuse the proxy; add logging
@@ -272,6 +279,8 @@
@Override
/** @hide */
protected final void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.print("Service component: "); pw.println(
+ ComponentName.flattenToShortString(mServiceComponentName));
if (mAutofillProxies != null) {
final int size = mAutofillProxies.size();
pw.print("Number proxies: "); pw.println(size);
@@ -301,12 +310,12 @@
/** @hide */
static final class AutofillProxy {
- static final int REPORT_EVENT_ON_SUCCESS = 1;
+ static final int REPORT_EVENT_NO_RESPONSE = 1;
static final int REPORT_EVENT_UI_SHOWN = 2;
static final int REPORT_EVENT_UI_DESTROYED = 3;
@IntDef(prefix = { "REPORT_EVENT_" }, value = {
- REPORT_EVENT_ON_SUCCESS,
+ REPORT_EVENT_NO_RESPONSE,
REPORT_EVENT_UI_SHOWN,
REPORT_EVENT_UI_DESTROYED
})
@@ -319,6 +328,8 @@
private final int mSessionId;
public final int taskId;
public final ComponentName componentName;
+ // Used for metrics / debug only
+ private String mServicePackageName;
@GuardedBy("mLock")
private AutofillId mFocusedId;
@GuardedBy("mLock")
@@ -349,6 +360,7 @@
private CancellationSignal mCancellationSignal;
private AutofillProxy(int sessionId, @NonNull IBinder client, int taskId,
+ @NonNull ComponentName serviceComponentName,
@NonNull ComponentName componentName, @NonNull AutofillId focusedId,
@Nullable AutofillValue focusedValue, long requestTime,
@NonNull IFillCallback callback, @NonNull CancellationSignal cancellationSignal) {
@@ -357,6 +369,7 @@
mCallback = callback;
this.taskId = taskId;
this.componentName = componentName;
+ mServicePackageName = serviceComponentName.getPackageName();
mFocusedId = focusedId;
mFocusedValue = focusedValue;
mFirstRequestTime = requestTime;
@@ -439,9 +452,9 @@
mCallback.cancel();
}
} catch (RemoteException e) {
- Slog.e(TAG, "failed to check current pending request status", e);
+ Log.e(TAG, "failed to check current pending request status", e);
}
- Slog.d(TAG, "mCallback is updated.");
+ Log.d(TAG, "mCallback is updated.");
}
mCallback = callback;
}
@@ -463,13 +476,17 @@
// Used (mostly) for metrics.
public void report(@ReportEvent int event) {
+ if (sVerbose) Log.v(TAG, "report(): " + event);
+ long duration = -1;
+ int type = MetricsEvent.TYPE_UNKNOWN;
switch (event) {
- case REPORT_EVENT_ON_SUCCESS:
+ case REPORT_EVENT_NO_RESPONSE:
+ type = MetricsEvent.TYPE_SUCCESS;
if (mFirstOnSuccessTime == 0) {
mFirstOnSuccessTime = SystemClock.elapsedRealtime();
+ duration = mFirstOnSuccessTime - mFirstRequestTime;
if (sDebug) {
- Slog.d(TAG, "Service responded in " + TimeUtils.formatDuration(
- mFirstOnSuccessTime - mFirstRequestTime));
+ Log.d(TAG, "Service responded nothing in " + formatDuration(duration));
}
}
try {
@@ -479,27 +496,25 @@
}
break;
case REPORT_EVENT_UI_SHOWN:
+ type = MetricsEvent.TYPE_OPEN;
if (mUiFirstShownTime == 0) {
mUiFirstShownTime = SystemClock.elapsedRealtime();
- if (sDebug) {
- Slog.d(TAG, "UI shown in " + TimeUtils.formatDuration(
- mUiFirstShownTime - mFirstRequestTime));
- }
+ duration = mUiFirstShownTime - mFirstRequestTime;
+ if (sDebug) Log.d(TAG, "UI shown in " + formatDuration(duration));
}
break;
case REPORT_EVENT_UI_DESTROYED:
+ type = MetricsEvent.TYPE_CLOSE;
if (mUiFirstDestroyedTime == 0) {
mUiFirstDestroyedTime = SystemClock.elapsedRealtime();
- if (sDebug) {
- Slog.d(TAG, "UI destroyed in " + TimeUtils.formatDuration(
- mUiFirstDestroyedTime - mFirstRequestTime));
- }
+ duration = mUiFirstDestroyedTime - mFirstRequestTime;
+ if (sDebug) Log.d(TAG, "UI destroyed in " + formatDuration(duration));
}
break;
default:
- Slog.w(TAG, "invalid event reported: " + event);
+ Log.w(TAG, "invalid event reported: " + event);
}
- // TODO(b/122858578): log metrics as well
+ logResponse(type, mServicePackageName, componentName, mSessionId, duration);
}
public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
@@ -527,19 +542,19 @@
if (mFirstOnSuccessTime > 0) {
final long responseTime = mFirstOnSuccessTime - mFirstRequestTime;
pw.print(prefix); pw.print("response time: ");
- TimeUtils.formatDuration(responseTime, pw); pw.println();
+ formatDuration(responseTime, pw); pw.println();
}
if (mUiFirstShownTime > 0) {
final long uiRenderingTime = mUiFirstShownTime - mFirstRequestTime;
pw.print(prefix); pw.print("UI rendering time: ");
- TimeUtils.formatDuration(uiRenderingTime, pw); pw.println();
+ formatDuration(uiRenderingTime, pw); pw.println();
}
if (mUiFirstDestroyedTime > 0) {
final long uiTotalTime = mUiFirstDestroyedTime - mFirstRequestTime;
pw.print(prefix); pw.print("UI life time: ");
- TimeUtils.formatDuration(uiTotalTime, pw); pw.println();
+ formatDuration(uiTotalTime, pw); pw.println();
}
}
diff --git a/core/java/android/service/autofill/augmented/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java
index 33e6a8c..0251386 100644
--- a/core/java/android/service/autofill/augmented/FillCallback.java
+++ b/core/java/android/service/autofill/augmented/FillCallback.java
@@ -50,8 +50,10 @@
public void onSuccess(@Nullable FillResponse response) {
if (sDebug) Log.d(TAG, "onSuccess(): " + response);
- mProxy.report(AutofillProxy.REPORT_EVENT_ON_SUCCESS);
- if (response == null) return;
+ if (response == null) {
+ mProxy.report(AutofillProxy.REPORT_EVENT_NO_RESPONSE);
+ return;
+ }
final FillWindow fillWindow = response.getFillWindow();
if (fillWindow != null) {
diff --git a/core/java/android/service/autofill/augmented/Helper.java b/core/java/android/service/autofill/augmented/Helper.java
new file mode 100644
index 0000000..501696f
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/Helper.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.service.autofill.augmented;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.metrics.LogMaker;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+/** @hide */
+public final class Helper {
+
+ private static final MetricsLogger sMetricsLogger = new MetricsLogger();
+
+ /**
+ * Logs a {@code MetricsEvent.AUTOFILL_AUGMENTED_RESPONSE} event.
+ */
+ public static void logResponse(int type, @NonNull String servicePackageName,
+ @NonNull ComponentName componentName, int mSessionId, long durationMs) {
+ final LogMaker log = new LogMaker(MetricsEvent.AUTOFILL_AUGMENTED_RESPONSE)
+ .setType(type)
+ .setComponentName(componentName)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SESSION_ID, mSessionId)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_DURATION, durationMs);
+ System.out.println("LOGGGO: " + log.getEntries()); // felipeal: tmp
+ sMetricsLogger.write(log);
+ }
+
+ private Helper() {
+ throw new UnsupportedOperationException("contains only static methods");
+ }
+}
diff --git a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
index 55e6141..efc8e87 100644
--- a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
+++ b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
@@ -30,6 +30,7 @@
import android.app.contentsuggestions.SelectionsRequest;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
import android.os.Bundle;
import android.os.Handler;
@@ -62,11 +63,15 @@
private final IContentSuggestionsService mInterface = new IContentSuggestionsService.Stub() {
@Override
public void provideContextImage(int taskId, GraphicBuffer contextImage,
- Bundle imageContextRequestExtras) {
+ int colorSpaceId, Bundle imageContextRequestExtras) {
Bitmap wrappedBuffer = null;
if (contextImage != null) {
- wrappedBuffer = Bitmap.wrapHardwareBuffer(contextImage, null);
+ ColorSpace colorSpace = null;
+ if (colorSpaceId >= 0 && colorSpaceId < ColorSpace.Named.values().length) {
+ colorSpace = ColorSpace.get(ColorSpace.Named.values()[colorSpaceId]);
+ }
+ wrappedBuffer = Bitmap.wrapHardwareBuffer(contextImage, colorSpace);
}
mHandler.sendMessage(
@@ -122,41 +127,29 @@
* Called by the system to provide the snapshot for the task associated with the given
* {@param taskId}.
*/
- public void onProcessContextImage(
- int taskId, @Nullable Bitmap contextImage, @NonNull Bundle extras) {
- // TODO(b/127532182): remove after next prebuilt drop.
- processContextImage(taskId, contextImage, extras);
- }
+ public abstract void onProcessContextImage(
+ int taskId, @Nullable Bitmap contextImage, @NonNull Bundle extras);
/**
* Content selections have been request through {@link ContentSuggestionsManager}, implementer
* should reply on the callback with selections.
*/
- public void onSuggestContentSelections(@NonNull SelectionsRequest request,
- @NonNull ContentSuggestionsManager.SelectionsCallback callback) {
- // TODO(b/127532182): remove after next prebuilt drop.
- suggestContentSelections(request, callback);
- }
+ public abstract void onSuggestContentSelections(@NonNull SelectionsRequest request,
+ @NonNull ContentSuggestionsManager.SelectionsCallback callback);
/**
* Content classifications have been request through {@link ContentSuggestionsManager},
* implementer should reply on the callback with classifications.
*/
- public void onClassifyContentSelections(@NonNull ClassificationsRequest request,
- @NonNull ContentSuggestionsManager.ClassificationsCallback callback) {
- // TODO(b/127532182): remove after next prebuilt drop.
- classifyContentSelections(request, callback);
- }
+ public abstract void onClassifyContentSelections(@NonNull ClassificationsRequest request,
+ @NonNull ContentSuggestionsManager.ClassificationsCallback callback);
/**
* User interactions have been reported through {@link ContentSuggestionsManager}, implementer
* should handle those interactions.
*/
- public void onNotifyInteraction(
- @NonNull String requestId, @NonNull Bundle interaction) {
- // TODO(b/127532182): remove after next prebuilt drop.
- notifyInteraction(requestId, interaction);
- }
+ public abstract void onNotifyInteraction(
+ @NonNull String requestId, @NonNull Bundle interaction);
private ContentSuggestionsManager.SelectionsCallback wrapSelectionsCallback(
ISelectionsCallback callback) {
@@ -179,42 +172,4 @@
}
});
}
-
-
- /**
- * For temporary compat reason, remove with b/127532182
- * @deprecated use {@link #onProcessContextImage(int, Bitmap, Bundle)} instead.
- */
- @Deprecated
- public void processContextImage(
- int taskId, @Nullable Bitmap contextImage, @NonNull Bundle extras) {
- }
-
- /**
- * For temporary compat reason, remove with b/127532182
- * @deprecated use {@link #onSuggestContentSelections(SelectionsRequest,
- * ContentSuggestionsManager.SelectionsCallback)} instead.
- */
- @Deprecated
- public void suggestContentSelections(@NonNull SelectionsRequest request,
- @NonNull ContentSuggestionsManager.SelectionsCallback callback) {
- }
-
- /**
- * For temporary compat reason, remove with b/127532182
- * @deprecated use {@link #onClassifyContentSelections(ClassificationsRequest,
- * ContentSuggestionsManager.ClassificationsCallback)} instead.
- */
- @Deprecated
- public void classifyContentSelections(@NonNull ClassificationsRequest request,
- @NonNull ContentSuggestionsManager.ClassificationsCallback callback) {
- }
-
- /**
- * For temporary compat reason, remove with b/127532182
- * @deprecated use {@link #onNotifyInteraction(String, Bundle)} instead.
- */
- @Deprecated
- public void notifyInteraction(@NonNull String requestId, @NonNull Bundle interaction) {
- }
}
diff --git a/core/java/android/service/contentsuggestions/IContentSuggestionsService.aidl b/core/java/android/service/contentsuggestions/IContentSuggestionsService.aidl
index 1926478..6240e00 100644
--- a/core/java/android/service/contentsuggestions/IContentSuggestionsService.aidl
+++ b/core/java/android/service/contentsuggestions/IContentSuggestionsService.aidl
@@ -32,6 +32,7 @@
void provideContextImage(
int taskId,
in GraphicBuffer contextImage,
+ int colorSpaceId,
in Bundle imageContextRequestExtras);
void suggestContentSelections(
in SelectionsRequest request,
diff --git a/core/java/android/service/notification/NotifyingApp.java b/core/java/android/service/notification/NotifyingApp.java
index a560623..a4fc5fd 100644
--- a/core/java/android/service/notification/NotifyingApp.java
+++ b/core/java/android/service/notification/NotifyingApp.java
@@ -26,27 +26,27 @@
*/
public final class NotifyingApp implements Parcelable, Comparable<NotifyingApp> {
- private int mUid;
+ private int mUserId;
private String mPkg;
private long mLastNotified;
public NotifyingApp() {}
protected NotifyingApp(Parcel in) {
- mUid = in.readInt();
+ mUserId = in.readInt();
mPkg = in.readString();
mLastNotified = in.readLong();
}
- public int getUid() {
- return mUid;
+ public int getUserId() {
+ return mUserId;
}
/**
- * Sets the uid of the package that sent the notification. Returns self.
+ * Sets the userid of the package that sent the notification. Returns self.
*/
- public NotifyingApp setUid(int mUid) {
- this.mUid = mUid;
+ public NotifyingApp setUserId(int mUserId) {
+ this.mUserId = mUserId;
return this;
}
@@ -74,7 +74,7 @@
return this;
}
- public static final @android.annotation.NonNull Creator<NotifyingApp> CREATOR = new Creator<NotifyingApp>() {
+ public static final @NonNull Creator<NotifyingApp> CREATOR = new Creator<NotifyingApp>() {
@Override
public NotifyingApp createFromParcel(Parcel in) {
return new NotifyingApp(in);
@@ -93,7 +93,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mUid);
+ dest.writeInt(mUserId);
dest.writeString(mPkg);
dest.writeLong(mLastNotified);
}
@@ -103,14 +103,14 @@
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NotifyingApp that = (NotifyingApp) o;
- return getUid() == that.getUid()
+ return getUserId() == that.getUserId()
&& getLastNotified() == that.getLastNotified()
&& Objects.equals(mPkg, that.mPkg);
}
@Override
public int hashCode() {
- return Objects.hash(getUid(), mPkg, getLastNotified());
+ return Objects.hash(getUserId(), mPkg, getLastNotified());
}
/**
@@ -119,10 +119,10 @@
@Override
public int compareTo(NotifyingApp o) {
if (getLastNotified() == o.getLastNotified()) {
- if (getUid() == o.getUid()) {
+ if (getUserId() == o.getUserId()) {
return getPackage().compareTo(o.getPackage());
}
- return Integer.compare(getUid(), o.getUid());
+ return Integer.compare(getUserId(), o.getUserId());
}
return -Long.compare(getLastNotified(), o.getLastNotified());
@@ -131,7 +131,7 @@
@Override
public String toString() {
return "NotifyingApp{"
- + "mUid=" + mUid
+ + "mUserId=" + mUserId
+ ", mPkg='" + mPkg + '\''
+ ", mLastNotified=" + mLastNotified
+ '}';
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index d32bdad..f1c870d 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -32,6 +32,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.util.Log;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.WindowManager;
@@ -79,6 +80,9 @@
*/
public class TileService extends Service {
+ private static final String TAG = "TileService";
+ private static final boolean DEBUG = false;
+
/**
* An activity that provides a user interface for adjusting TileService
* preferences. Optional but recommended for apps that implement a
@@ -381,18 +385,26 @@
private static final int MSG_TILE_CLICKED = 5;
private static final int MSG_UNLOCK_COMPLETE = 6;
private static final int MSG_START_SUCCESS = 7;
+ private final String mTileServiceName;
public H(Looper looper) {
super(looper);
+ mTileServiceName = TileService.this.getClass().getSimpleName();
+ }
+
+ private void logMessage(String message) {
+ Log.d(TAG, mTileServiceName + " Handler - " + message);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_TILE_ADDED:
+ if (DEBUG) logMessage("MSG_TILE_ADDED");
TileService.this.onTileAdded();
break;
case MSG_TILE_REMOVED:
+ if (DEBUG) logMessage("MSG_TILE_REMOVED");
if (mListening) {
mListening = false;
TileService.this.onStopListening();
@@ -400,27 +412,32 @@
TileService.this.onTileRemoved();
break;
case MSG_STOP_LISTENING:
+ if (DEBUG) logMessage("MSG_STOP_LISTENING");
if (mListening) {
mListening = false;
TileService.this.onStopListening();
}
break;
case MSG_START_LISTENING:
+ if (DEBUG) logMessage("MSG_START_LISTENING");
if (!mListening) {
mListening = true;
TileService.this.onStartListening();
}
break;
case MSG_TILE_CLICKED:
+ if (DEBUG) logMessage("MSG_TILE_CLICKED");
mToken = (IBinder) msg.obj;
TileService.this.onClick();
break;
case MSG_UNLOCK_COMPLETE:
+ if (DEBUG) logMessage("MSG_UNLOCK_COMPLETE");
if (mUnlockRunnable != null) {
mUnlockRunnable.run();
}
break;
case MSG_START_SUCCESS:
+ if (DEBUG) logMessage("MSG_START_SUCCESS");
try {
mService.onStartSuccessful(mTileToken);
} catch (RemoteException e) {
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 8819d22..0feab4d 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1947,16 +1947,21 @@
* @hide
*/
void forceToEnd(ViewGroup sceneRoot) {
- ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
+ final ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
int numOldAnims = runningAnimators.size();
- if (sceneRoot != null) {
- WindowId windowId = sceneRoot.getWindowId();
- for (int i = numOldAnims - 1; i >= 0; i--) {
- AnimationInfo info = runningAnimators.valueAt(i);
- if (info.view != null && windowId != null && windowId.equals(info.windowId)) {
- Animator anim = runningAnimators.keyAt(i);
- anim.end();
- }
+ if (sceneRoot == null || numOldAnims == 0) {
+ return;
+ }
+
+ WindowId windowId = sceneRoot.getWindowId();
+ final ArrayMap<Animator, AnimationInfo> oldAnimators = new ArrayMap(runningAnimators);
+ runningAnimators.clear();
+
+ for (int i = numOldAnims - 1; i >= 0; i--) {
+ AnimationInfo info = oldAnimators.valueAt(i);
+ if (info.view != null && windowId != null && windowId.equals(info.windowId)) {
+ Animator anim = oldAnimators.keyAt(i);
+ anim.end();
}
}
}
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index 7653c77..d899dde 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -461,6 +461,7 @@
public K keyAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
return (K)mArray[index << 1];
@@ -480,6 +481,7 @@
public V valueAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
return (V)mArray[(index << 1) + 1];
@@ -500,6 +502,7 @@
public V setValueAt(int index, V value) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
index = (index << 1) + 1;
@@ -703,6 +706,7 @@
public V removeAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index 610641d..3fa914f 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -368,6 +368,7 @@
public E valueAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
return valueAtUnchecked(index);
@@ -545,6 +546,7 @@
public E removeAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
final Object old = mArray[index];
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index e8b0d92..c42dc81 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -36,12 +36,7 @@
public static final String PERSIST_PREFIX = "persist." + FFLAG_OVERRIDE_PREFIX;
public static final String SEAMLESS_TRANSFER = "settings_seamless_transfer";
public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
- public static final String SAFETY_HUB = "settings_safety_hub";
public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
- public static final String FORCE_GLOBAL_ACTIONS_GRID_ENABLED =
- "settings_global_actions_force_grid_enabled";
- public static final String GLOBAL_ACTIONS_PANEL_ENABLED =
- "settings_global_actions_panel_enabled";
public static final String PIXEL_WALLPAPER_CATEGORY_SWITCH =
"settings_pixel_wallpaper_category_switch";
public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
@@ -57,10 +52,7 @@
DEFAULT_FLAGS.put(DYNAMIC_SYSTEM, "false");
DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
- DEFAULT_FLAGS.put(SAFETY_HUB, "true");
DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false");
- DEFAULT_FLAGS.put(FORCE_GLOBAL_ACTIONS_GRID_ENABLED, "false");
- DEFAULT_FLAGS.put(GLOBAL_ACTIONS_PANEL_ENABLED, "true");
DEFAULT_FLAGS.put(PIXEL_WALLPAPER_CATEGORY_SWITCH, "false");
DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
}
diff --git a/core/java/android/util/LauncherIcons.java b/core/java/android/util/LauncherIcons.java
index cc9991a..8501eb5 100644
--- a/core/java/android/util/LauncherIcons.java
+++ b/core/java/android/util/LauncherIcons.java
@@ -15,6 +15,7 @@
*/
package android.util;
+import android.app.ActivityThread;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -102,16 +103,17 @@
}
public Drawable getBadgedDrawable(Drawable base, int foregroundRes, int backgroundColor) {
- Resources sysRes = Resources.getSystem();
+ Resources overlayableRes =
+ ActivityThread.currentActivityThread().getApplication().getResources();
- Drawable badgeShadow = sysRes.getDrawable(
+ Drawable badgeShadow = overlayableRes.getDrawable(
com.android.internal.R.drawable.ic_corp_icon_badge_shadow);
- Drawable badgeColor = sysRes.getDrawable(
+ Drawable badgeColor = overlayableRes.getDrawable(
com.android.internal.R.drawable.ic_corp_icon_badge_color)
.getConstantState().newDrawable().mutate();
- Drawable badgeForeground = sysRes.getDrawable(foregroundRes);
+ Drawable badgeForeground = overlayableRes.getDrawable(foregroundRes);
badgeForeground.setTint(backgroundColor);
Drawable[] drawables = base == null
diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java
index 698b5b0..d3b2c46 100644
--- a/core/java/android/util/LongSparseArray.java
+++ b/core/java/android/util/LongSparseArray.java
@@ -151,6 +151,7 @@
public void removeAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
if (mValues[index] != DELETED) {
@@ -249,6 +250,7 @@
public long keyAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
if (mGarbage) {
@@ -278,6 +280,7 @@
public E valueAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
if (mGarbage) {
@@ -300,6 +303,7 @@
public void setValueAt(int index, E value) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
if (mGarbage) {
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index b7c3e18..7b7eea0 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -179,6 +179,7 @@
public long keyAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
return mKeys[index];
@@ -203,6 +204,7 @@
public long valueAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
return mValues[index];
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index 74fea3f..80b1607 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -20,9 +20,8 @@
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
-import dalvik.system.CloseGuard;
-
import libcore.io.IoUtils;
+import dalvik.system.CloseGuard;
import java.io.Closeable;
import java.io.IOException;
@@ -57,7 +56,7 @@
private final boolean mIsOwner;
private final long mMemoryAddr;
- private ParcelFileDescriptor mFd;
+ private int mFd = -1;
/**
* Creates a new instance.
@@ -72,8 +71,8 @@
}
mIsOwner = true;
final String name = UUID.randomUUID().toString();
- mFd = ParcelFileDescriptor.adoptFd(nativeCreate(name, size));
- mMemoryAddr = nativeOpen(mFd.getFd(), mIsOwner);
+ mFd = nativeCreate(name, size);
+ mMemoryAddr = nativeOpen(mFd, mIsOwner);
mCloseGuard.open("close");
}
@@ -83,8 +82,8 @@
if (pfd == null) {
throw new IOException("No backing file descriptor");
}
- mFd = ParcelFileDescriptor.adoptFd(pfd.detachFd());
- mMemoryAddr = nativeOpen(mFd.getFd(), mIsOwner);
+ mFd = pfd.detachFd();
+ mMemoryAddr = nativeOpen(mFd, mIsOwner);
mCloseGuard.open("close");
}
@@ -106,7 +105,7 @@
public int get(int index) throws IOException {
enforceNotClosed();
enforceValidIndex(index);
- return nativeGet(mFd.getFd(), mMemoryAddr, index);
+ return nativeGet(mFd, mMemoryAddr, index);
}
/**
@@ -122,7 +121,7 @@
enforceNotClosed();
enforceWritable();
enforceValidIndex(index);
- nativeSet(mFd.getFd(), mMemoryAddr, index, value);
+ nativeSet(mFd, mMemoryAddr, index, value);
}
/**
@@ -132,7 +131,7 @@
*/
public int size() throws IOException {
enforceNotClosed();
- return nativeSize(mFd.getFd());
+ return nativeSize(mFd);
}
/**
@@ -143,9 +142,8 @@
@Override
public void close() throws IOException {
if (!isClosed()) {
- nativeClose(mFd.getFd(), mMemoryAddr, mIsOwner);
- mFd.close();
- mFd = null;
+ nativeClose(mFd, mMemoryAddr, mIsOwner);
+ mFd = -1;
mCloseGuard.close();
}
}
@@ -154,7 +152,7 @@
* @return Whether this array is closed and shouldn't be used.
*/
public boolean isClosed() {
- return mFd == null;
+ return mFd == -1;
}
@Override
@@ -177,8 +175,13 @@
@Override
public void writeToParcel(Parcel parcel, int flags) {
- // Don't let writing to a parcel to close our fd - plz
- parcel.writeParcelable(mFd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(mFd);
+ try {
+ // Don't let writing to a parcel to close our fd - plz
+ parcel.writeParcelable(pfd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ } finally {
+ pfd.detachFd();
+ }
}
@Override
@@ -192,13 +195,13 @@
if (getClass() != obj.getClass()) {
return false;
}
-
- return false;
+ MemoryIntArray other = (MemoryIntArray) obj;
+ return mFd == other.mFd;
}
@Override
public int hashCode() {
- return mFd.hashCode();
+ return mFd;
}
private void enforceNotClosed() {
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 7a8c780..0a15db2 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -176,6 +176,7 @@
public void removeAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
if (mValues[index] != DELETED) {
@@ -290,6 +291,7 @@
public int keyAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
if (mGarbage) {
@@ -319,6 +321,7 @@
public E valueAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
if (mGarbage) {
@@ -341,6 +344,7 @@
public void setValueAt(int index, E value) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
if (mGarbage) {
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index 5574047..d6e0e53 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -175,6 +175,7 @@
public int keyAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
return mKeys[index];
@@ -199,6 +200,7 @@
public boolean valueAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
return mValues[index];
@@ -215,6 +217,7 @@
public void setValueAt(int index, boolean value) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
mValues[index] = value;
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 84f9269..1ca1717 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -179,6 +179,7 @@
public int keyAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
return mKeys[index];
@@ -203,6 +204,7 @@
public int valueAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
return mValues[index];
@@ -219,6 +221,7 @@
public void setValueAt(int index, int value) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
mValues[index] = value;
diff --git a/core/java/android/util/SparseLongArray.java b/core/java/android/util/SparseLongArray.java
index 00e39a9..b0916d3 100644
--- a/core/java/android/util/SparseLongArray.java
+++ b/core/java/android/util/SparseLongArray.java
@@ -189,6 +189,7 @@
public int keyAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
return mKeys[index];
@@ -213,6 +214,7 @@
public long valueAt(int index) {
if (index >= mSize && UtilConfig.sThrowExceptionForUpperArrayOutOfBounds) {
// The array might be slightly bigger than mSize, in which case, indexing won't fail.
+ // Check if exception should be thrown outside of the critical path.
throw new ArrayIndexOutOfBoundsException(index);
}
return mValues[index];
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index c730fe2..b347a78 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -621,18 +621,6 @@
*/
void setShouldShowIme(int displayId, boolean shouldShow);
- /**
- * Reparent the top layers for a display to the requested surfaceControl. The display that
- * is going to be re-parented (the displayId passed in) needs to have been created by the same
- * process that is requesting the re-parent. This is to ensure clients can't just re-parent
- * display content info to any SurfaceControl, as this would be a security issue.
- *
- * @param displayId The id of the display.
- * @param surfaceControlHandle The SurfaceControl that the top level layers for the
- * display should be re-parented to.
- */
- void reparentDisplayContent(int displayId, in SurfaceControl sc);
-
/**
* Waits for transactions to get applied before injecting input.
* This includes waiting for the input windows to get sent to InputManager.
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index b52fdb8..d269323 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -257,6 +257,31 @@
void updatePointerIcon(IWindow window);
/**
+ * Reparent the top layers for a display to the requested SurfaceControl. The display that is
+ * going to be re-parented (the displayId passed in) needs to have been created by the same
+ * process that is requesting the re-parent. This is to ensure clients can't just re-parent
+ * display content info to any SurfaceControl, as this would be a security issue.
+ *
+ * @param window The window which owns the SurfaceControl. This indicates the z-order of the
+ * windows of this display against the windows on the parent display.
+ * @param sc The SurfaceControl that the top level layers for the display should be re-parented
+ * to.
+ * @param displayId The id of the display to be re-parented.
+ */
+ void reparentDisplayContent(IWindow window, in SurfaceControl sc, int displayId);
+
+ /**
+ * Update the location of a child display in its parent window. This enables windows in the
+ * child display to compute the global transformation matrix.
+ *
+ * @param window The parent window of the display.
+ * @param x The x coordinate in the parent window.
+ * @param y The y coordinate in the parent window.
+ * @param displayId The id of the display to be notified.
+ */
+ void updateDisplayContentLocation(IWindow window, int x, int y, int displayId);
+
+ /**
* Update a tap exclude region identified by provided id in the window. Touches on this region
* will neither be dispatched to this window nor change the focus to this window. Passing an
* invalid region will remove the area from the exclude region of this window.
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index d415387..83abf1a 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -173,6 +173,6 @@
}
private InputMethodManager getImm() {
- return mController.getViewRoot().mDisplayContext.getSystemService(InputMethodManager.class);
+ return mController.getViewRoot().mContext.getSystemService(InputMethodManager.class);
}
}
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 04ac922..c2f9601 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -24,7 +24,6 @@
import android.graphics.Paint;
import android.graphics.RecordingCanvas;
import android.graphics.RenderNode;
-import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.SparseIntArray;
@@ -289,7 +288,8 @@
throw new UnsupportedOperationException();
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ /** @hide */
+ @UnsupportedAppUsage
public void setTarget(View view) {
mViewTarget = view;
setTarget(mViewTarget.mRenderNode);
@@ -301,7 +301,7 @@
}
/** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.O)
+ @UnsupportedAppUsage
public void setTarget(DisplayListCanvas canvas) {
setTarget((RecordingCanvas) canvas);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index d67c884..63e1485 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -2660,6 +2660,9 @@
*/
@NonNull
public Transaction merge(@NonNull Transaction other) {
+ if (this == other) {
+ return this;
+ }
mResizedSurfaces.putAll(other.mResizedSurfaces);
other.mResizedSurfaces.clear();
nativeMergeTransaction(mNativeObject, other.mNativeObject);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 8070e76..1812d29 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -33,6 +33,7 @@
import android.graphics.RenderNode;
import android.os.Build;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -119,11 +120,10 @@
final Rect mScreenRect = new Rect();
SurfaceSession mSurfaceSession;
- SurfaceControl mSurfaceControl;
+ SurfaceControlWithBackground mSurfaceControl;
// In the case of format changes we switch out the surface in-place
// we need to preserve the old one until the new one has drawn.
- SurfaceControl mDeferredDestroySurfaceControl;
- SurfaceControl mBackgroundControl;
+ SurfaceControlWithBackground mDeferredDestroySurfaceControl;
final Rect mTmpRect = new Rect();
final Configuration mConfiguration = new Configuration();
@@ -487,29 +487,6 @@
}
}
- private void updateBackgroundVisibilityInTransaction() {
- if (mBackgroundControl == null) {
- return;
- }
- if ((mSubLayer < 0) && ((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)) {
- mBackgroundControl.show();
- mBackgroundControl.setLayer(Integer.MIN_VALUE);
- } else {
- mBackgroundControl.hide();
- }
- }
-
- private void releaseSurfaces() {
- if (mSurfaceControl != null) {
- mSurfaceControl.remove();
- mSurfaceControl = null;
- }
- if (mBackgroundControl != null) {
- mBackgroundControl.remove();
- mBackgroundControl = null;
- }
- }
-
/** @hide */
protected void updateSurface() {
if (!mHaveFrame) {
@@ -576,21 +553,14 @@
updateOpaqueFlag();
final String name = "SurfaceView - " + viewRoot.getTitle().toString();
- mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
- .setName(name)
- .setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)
- .setBufferSize(mSurfaceWidth, mSurfaceHeight)
- .setFormat(mFormat)
- .setParent(viewRoot.getSurfaceControl())
- .setFlags(mSurfaceFlags)
- .build();
- mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession)
- .setName("Background for -" + name)
- .setOpaque(true)
- .setColorLayer()
- .setParent(mSurfaceControl)
- .build();
-
+ mSurfaceControl = new SurfaceControlWithBackground(
+ name,
+ (mSurfaceFlags & SurfaceControl.OPAQUE) != 0,
+ new SurfaceControl.Builder(mSurfaceSession)
+ .setBufferSize(mSurfaceWidth, mSurfaceHeight)
+ .setFormat(mFormat)
+ .setParent(viewRoot.getSurfaceControl())
+ .setFlags(mSurfaceFlags));
} else if (mSurfaceControl == null) {
return;
}
@@ -607,13 +577,11 @@
SurfaceControl.openTransaction();
try {
mSurfaceControl.setLayer(mSubLayer);
-
if (mViewVisibility) {
mSurfaceControl.show();
} else {
mSurfaceControl.hide();
}
- updateBackgroundVisibilityInTransaction();
// While creating the surface, we will set it's initial
// geometry. Outside of that though, we should generally
@@ -699,7 +667,7 @@
}
if (creating) {
- mSurface.copyFrom(mSurfaceControl);
+ mSurface.copyFrom(mSurfaceControl.mForegroundControl);
}
if (sizeChanged && getContext().getApplicationInfo().targetSdkVersion
@@ -709,7 +677,7 @@
// existing {@link Surface} will be ignored when the size changes.
// Therefore, we must explicitly recreate the {@link Surface} in these
// cases.
- mSurface.createFrom(mSurfaceControl);
+ mSurface.createFrom(mSurfaceControl.mForegroundControl);
}
if (visible && mSurface.isValid()) {
@@ -756,7 +724,8 @@
if (mSurfaceControl != null && !mSurfaceCreated) {
mSurface.release();
- releaseSurfaces();
+ mSurfaceControl.remove();
+ mSurfaceControl = null;
}
}
} catch (Exception ex) {
@@ -848,12 +817,17 @@
position.width() / (float) mSurfaceWidth,
0.0f, 0.0f,
position.height() / (float) mSurfaceHeight);
+ if (mViewVisibility) {
+ mRtTransaction.show(surface);
+ }
+
}
private void setParentSpaceRectangle(Rect position, long frameNumber) {
final ViewRootImpl viewRoot = getViewRootImpl();
- applySurfaceTransforms(mSurfaceControl, position, frameNumber);
+ applySurfaceTransforms(mSurfaceControl.mForegroundControl, position, frameNumber);
+ applySurfaceTransforms(mSurfaceControl.mBackgroundControl, position, frameNumber);
applyChildSurfaceTransaction_renderWorker(mRtTransaction, viewRoot.mSurface,
frameNumber);
@@ -914,27 +888,18 @@
if (mSurfaceControl == null) {
return;
}
- if (mRtHandlingPositionUpdates) {
- mRtHandlingPositionUpdates = false;
- // This callback will happen while the UI thread is blocked, so we can
- // safely access other member variables at this time.
- // So do what the UI thread would have done if RT wasn't handling position
- // updates.
- if (!mScreenRect.isEmpty() && !mScreenRect.equals(mRTLastReportedPosition)) {
- try {
- if (DEBUG) {
- Log.d(TAG, String.format("%d updateSurfacePosition, "
- + "postion = [%d, %d, %d, %d]",
- System.identityHashCode(this),
- mScreenRect.left, mScreenRect.top,
- mScreenRect.right, mScreenRect.bottom));
- }
- setParentSpaceRectangle(mScreenRect, frameNumber);
- } catch (Exception ex) {
- Log.e(TAG, "Exception configuring surface", ex);
- }
- }
+
+ if (frameNumber > 0) {
+ final ViewRootImpl viewRoot = getViewRootImpl();
+
+ mRtTransaction.deferTransactionUntilSurface(mSurfaceControl.mForegroundControl, viewRoot.mSurface,
+ frameNumber);
+ mRtTransaction.deferTransactionUntilSurface(mSurfaceControl.mBackgroundControl, viewRoot.mSurface,
+ frameNumber);
}
+ mRtTransaction.hide(mSurfaceControl.mForegroundControl);
+ mRtTransaction.hide(mSurfaceControl.mBackgroundControl);
+ mRtTransaction.apply();
}
};
@@ -980,19 +945,7 @@
* @hide
*/
public void setResizeBackgroundColor(int bgColor) {
- if (mBackgroundControl == null) {
- return;
- }
-
- final float[] colorComponents = new float[] { Color.red(bgColor) / 255.f,
- Color.green(bgColor) / 255.f, Color.blue(bgColor) / 255.f };
-
- SurfaceControl.openTransaction();
- try {
- mBackgroundControl.setColor(colorComponents);
- } finally {
- SurfaceControl.closeTransaction();
- }
+ mSurfaceControl.setBackgroundColor(bgColor);
}
@UnsupportedAppUsage
@@ -1176,6 +1129,134 @@
* @return The SurfaceControl for this SurfaceView.
*/
public SurfaceControl getSurfaceControl() {
- return mSurfaceControl;
+ return mSurfaceControl.mForegroundControl;
+ }
+
+ class SurfaceControlWithBackground {
+ SurfaceControl mForegroundControl;
+ SurfaceControl mBackgroundControl;
+ private boolean mOpaque = true;
+ public boolean mVisible = false;
+
+ public SurfaceControlWithBackground(String name, boolean opaque, SurfaceControl.Builder b)
+ throws Exception {
+ mForegroundControl = b.setName(name).build();
+ mBackgroundControl = b.setName("Background for -" + name)
+ // Unset the buffer size of the background color layer.
+ .setBufferSize(0, 0)
+ .setColorLayer()
+ .build();
+
+ mOpaque = opaque;
+ }
+
+ public void setAlpha(float alpha) {
+ mForegroundControl.setAlpha(alpha);
+ mBackgroundControl.setAlpha(alpha);
+ }
+
+ public void setLayer(int zorder) {
+ mForegroundControl.setLayer(zorder);
+ // -3 is below all other child layers as SurfaceView never goes below -2
+ mBackgroundControl.setLayer(-3);
+ }
+
+ public void setPosition(float x, float y) {
+ mForegroundControl.setPosition(x, y);
+ mBackgroundControl.setPosition(x, y);
+ }
+
+ public void setBufferSize(int w, int h) {
+ mForegroundControl.setBufferSize(w, h);
+ // The background surface is a color layer so we do not set a size.
+ }
+
+ public void setWindowCrop(Rect crop) {
+ mForegroundControl.setWindowCrop(crop);
+ mBackgroundControl.setWindowCrop(crop);
+ }
+
+ public void setWindowCrop(int width, int height) {
+ mForegroundControl.setWindowCrop(width, height);
+ mBackgroundControl.setWindowCrop(width, height);
+ }
+
+ public void setLayerStack(int layerStack) {
+ mForegroundControl.setLayerStack(layerStack);
+ mBackgroundControl.setLayerStack(layerStack);
+ }
+
+ public void setOpaque(boolean isOpaque) {
+ mForegroundControl.setOpaque(isOpaque);
+ mOpaque = isOpaque;
+ updateBackgroundVisibility();
+ }
+
+ public void setSecure(boolean isSecure) {
+ mForegroundControl.setSecure(isSecure);
+ }
+
+ public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+ mForegroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
+ mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
+ }
+
+ public void hide() {
+ mForegroundControl.hide();
+ mVisible = false;
+ updateBackgroundVisibility();
+ }
+
+ public void show() {
+ mForegroundControl.show();
+ mVisible = true;
+ updateBackgroundVisibility();
+ }
+
+ public void remove() {
+ mForegroundControl.remove();
+ mBackgroundControl.remove();
+ }
+
+ public void release() {
+ mForegroundControl.release();
+ mBackgroundControl.release();
+ }
+
+ public void setTransparentRegionHint(Region region) {
+ mForegroundControl.setTransparentRegionHint(region);
+ mBackgroundControl.setTransparentRegionHint(region);
+ }
+
+ public void deferTransactionUntil(IBinder handle, long frame) {
+ mForegroundControl.deferTransactionUntil(handle, frame);
+ mBackgroundControl.deferTransactionUntil(handle, frame);
+ }
+
+ public void deferTransactionUntil(Surface barrier, long frame) {
+ mForegroundControl.deferTransactionUntil(barrier, frame);
+ mBackgroundControl.deferTransactionUntil(barrier, frame);
+ }
+
+ /** Set the color to fill the background with. */
+ private void setBackgroundColor(int bgColor) {
+ final float[] colorComponents = new float[] { Color.red(bgColor) / 255.f,
+ Color.green(bgColor) / 255.f, Color.blue(bgColor) / 255.f };
+
+ SurfaceControl.openTransaction();
+ try {
+ mBackgroundControl.setColor(colorComponents);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+
+ void updateBackgroundVisibility() {
+ if (mOpaque && mVisible) {
+ mBackgroundControl.show();
+ } else {
+ mBackgroundControl.hide();
+ }
+ }
}
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 3bae4b8..3d3d5dc 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -177,7 +177,7 @@
* Forces smart-dark to be always on.
* @hide
*/
- public static final String DEBUG_FORCE_DARK = "persist.hwui.force_dark";
+ public static final String DEBUG_FORCE_DARK = "debug.hwui.force_dark";
public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b813bc3..e835675 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -283,13 +283,7 @@
@GuardedBy("mWindowCallbacks")
final ArrayList<WindowCallbacks> mWindowCallbacks = new ArrayList<>();
@UnsupportedAppUsage
- final Context mContext;
- /**
- * TODO(b/116349163): Check if we can merge this into {@link #mContext}.
- * @hide
- */
- @NonNull
- public Context mDisplayContext;
+ public final Context mContext;
@UnsupportedAppUsage
final IWindowSession mWindowSession;
@@ -595,7 +589,6 @@
public ViewRootImpl(Context context, Display display) {
mContext = context;
- mDisplayContext = context.createDisplayContext(display);
mWindowSession = WindowManagerGlobal.getWindowSession();
mDisplay = display;
mBasePackageName = context.getBasePackageName();
@@ -1379,7 +1372,7 @@
} else {
mDisplay = preferredDisplay;
}
- mDisplayContext = mContext.createDisplayContext(mDisplay);
+ mContext.updateDisplay(mDisplay.getDisplayId());
}
void pokeDrawLockIfNeeded() {
@@ -2725,7 +2718,7 @@
.mayUseInputMethod(mWindowAttributes.flags);
if (imTarget != mLastWasImTarget) {
mLastWasImTarget = imTarget;
- InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
+ InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
if (imm != null && imTarget) {
imm.onPreWindowFocus(mView, hasWindowFocus);
imm.onPostWindowFocus(mView, mView.findFocus(),
@@ -2859,7 +2852,7 @@
mLastWasImTarget = WindowManager.LayoutParams
.mayUseInputMethod(mWindowAttributes.flags);
- InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
+ InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
imm.onPreWindowFocus(mView, hasWindowFocus);
}
@@ -4564,8 +4557,7 @@
enqueueInputEvent(event, null, 0, true);
} break;
case MSG_CHECK_FOCUS: {
- InputMethodManager imm =
- mDisplayContext.getSystemService(InputMethodManager.class);
+ InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
if (imm != null) {
imm.checkFocus();
}
@@ -5110,7 +5102,7 @@
@Override
protected int onProcess(QueuedInputEvent q) {
if (mLastWasImTarget && !isInLocalFocusMode()) {
- InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
+ InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
if (imm != null) {
final InputEvent event = q.mEvent;
if (DEBUG_IMF) Log.v(mTag, "Sending input event to IME: " + event);
@@ -8279,6 +8271,7 @@
void changeCanvasOpacity(boolean opaque) {
Log.d(mTag, "changeCanvasOpacity: opaque=" + opaque);
+ opaque = opaque & ((mView.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0);
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mThreadedRenderer.setOpaque(opaque);
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index cbcc057..9436633 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1090,6 +1090,7 @@
*
* @hide
*/
+ @UnsupportedAppUsage
public void addPrivateFlags(int flags) {
setPrivateFlags(flags, flags);
}
diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
index 2c79299..b387a68 100644
--- a/core/java/android/view/autofill/AutofillId.java
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -16,6 +16,7 @@
package android.view.autofill;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -34,10 +35,10 @@
private static final int FLAG_HAS_SESSION = 0x4;
private final int mViewId;
- private final int mFlags;
+ private int mFlags;
private final int mVirtualIntId;
private final long mVirtualLongId;
- private final int mSessionId;
+ private int mSessionId;
/** @hide */
@TestApi
@@ -72,6 +73,12 @@
}
/** @hide */
+ public static AutofillId withoutSession(@NonNull AutofillId id) {
+ final int flags = id.mFlags & ~FLAG_HAS_SESSION;
+ return new AutofillId(flags, id.mViewId, id.mVirtualLongId, NO_SESSION);
+ }
+
+ /** @hide */
public int getViewId() {
return mViewId;
}
@@ -135,7 +142,8 @@
return !isVirtualInt() && !isVirtualLong();
}
- private boolean hasSession() {
+ /** @hide */
+ public boolean hasSession() {
return (mFlags & FLAG_HAS_SESSION) != 0;
}
@@ -144,6 +152,18 @@
return mSessionId;
}
+ /** @hide */
+ public void setSessionId(int sessionId) {
+ mFlags |= FLAG_HAS_SESSION;
+ mSessionId = sessionId;
+ }
+
+ /** @hide */
+ public void resetSessionId() {
+ mFlags &= ~FLAG_HAS_SESSION;
+ mSessionId = NO_SESSION;
+ }
+
/////////////////////////////////
// Object "contract" methods. //
/////////////////////////////////
@@ -172,6 +192,17 @@
return true;
}
+ /** @hide */
+ @TestApi
+ public boolean equalsIgnoreSession(@Nullable AutofillId other) {
+ if (this == other) return true;
+ if (other == null) return false;
+ if (mViewId != other.mViewId) return false;
+ if (mVirtualIntId != other.mVirtualIntId) return false;
+ if (mVirtualLongId != other.mVirtualLongId) return false;
+ return true;
+ }
+
@Override
public String toString() {
final StringBuilder builder = new StringBuilder().append(mViewId);
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 6503a80..c36b894 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -48,6 +48,7 @@
import android.service.autofill.UserData;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.DebugUtils;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -229,7 +230,8 @@
/** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4;
/** @hide */ public static final int FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY = 0x8;
- /** @hide */ public static final int FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY = 0x1;
+ // NOTE: flag below is used by the session start receiver only, hence it can have values above
+ /** @hide */ public static final int RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY = 0x1;
/** @hide */
public static final int DEFAULT_LOGGING_LEVEL = Build.IS_DEBUGGABLE
@@ -521,7 +523,7 @@
private boolean mForAugmentedAutofillOnly;
/**
- * When set, standard autofill is enabled, but sessions can still be created for augmented
+ * When set, standard autofill is disabled, but sessions can still be created for augmented
* autofill only.
*/
@GuardedBy("mLock")
@@ -969,6 +971,13 @@
startSessionLocked(id, null, value, flags);
} else {
// Update focus on existing session.
+ if (mForAugmentedAutofillOnly && (flags & FLAG_MANUAL_REQUEST) != 0) {
+ if (sDebug) {
+ Log.d(TAG, "notifyViewEntered(" + id + "): resetting "
+ + "mForAugmentedAutofillOnly on manual request");
+ }
+ mForAugmentedAutofillOnly = false;
+ }
updateSessionLocked(id, null, value, ACTION_VIEW_ENTERED, flags);
}
addEnteredIdLocked(id);
@@ -1126,6 +1135,13 @@
startSessionLocked(id, bounds, null, flags);
} else {
// Update focus on existing session.
+ if (mForAugmentedAutofillOnly && (flags & FLAG_MANUAL_REQUEST) != 0) {
+ if (sDebug) {
+ Log.d(TAG, "notifyViewEntered(" + id + "): resetting "
+ + "mForAugmentedAutofillOnly on manual request");
+ }
+ mForAugmentedAutofillOnly = false;
+ }
updateSessionLocked(id, bounds, null, ACTION_VIEW_ENTERED, flags);
}
addEnteredIdLocked(id);
@@ -1139,6 +1155,7 @@
if (mEnteredIds == null) {
mEnteredIds = new ArraySet<>(1);
}
+ id.resetSessionId();
mEnteredIds.add(id);
}
@@ -1694,6 +1711,16 @@
+ ", enabledAugmentedOnly=" + mEnabledForAugmentedAutofillOnly
+ ", enteredIds=" + mEnteredIds);
}
+ // We need to reset the augmented-only state when a manual request is made, as it's possible
+ // that the service returned null for the first request and now the user is manually
+ // requesting autofill to trigger a custom UI provided by the service.
+ if (mForAugmentedAutofillOnly && !mEnabledForAugmentedAutofillOnly
+ && (flags & FLAG_MANUAL_REQUEST) != 0) {
+ if (sVerbose) {
+ Log.v(TAG, "resetting mForAugmentedAutofillOnly on manual autofill request");
+ }
+ mForAugmentedAutofillOnly = false;
+ }
if (mState != STATE_UNKNOWN && !isFinishedLocked() && (flags & FLAG_MANUAL_REQUEST) == 0) {
if (sVerbose) {
Log.v(TAG, "not automatically starting session for " + id
@@ -1716,7 +1743,7 @@
mState = STATE_ACTIVE;
}
final int extraFlags = receiver.getOptionalExtraIntResult(0);
- if ((extraFlags & FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY) != 0) {
+ if ((extraFlags & RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY) != 0) {
if (sDebug) Log.d(TAG, "startSession(" + componentName + "): for augmented only");
mForAugmentedAutofillOnly = true;
}
@@ -2010,10 +2037,20 @@
public static final int SET_STATE_FLAG_DEBUG = 0x08;
/** @hide */
public static final int SET_STATE_FLAG_VERBOSE = 0x10;
+ /** @hide */
+ public static final int SET_STATE_FLAG_FOR_AUTOFILL_ONLY = 0x20;
private void setState(int flags) {
- if (sVerbose) Log.v(TAG, "setState(" + flags + ")");
+ if (sVerbose) {
+ Log.v(TAG, "setState(" + flags + ": " + DebugUtils.flagsToString(AutofillManager.class,
+ "SET_STATE_FLAG_", flags) + ")");
+ }
synchronized (mLock) {
+ if ((flags & SET_STATE_FLAG_FOR_AUTOFILL_ONLY) != 0) {
+ mForAugmentedAutofillOnly = true;
+ // NOTE: returning right away as this is the only flag set, at least currently...
+ return;
+ }
mEnabled = (flags & SET_STATE_FLAG_ENABLED) != 0;
if (!mEnabled || (flags & SET_STATE_FLAG_RESET_SESSION) != 0) {
// Reset the session state
@@ -2177,6 +2214,9 @@
private void setTrackedViews(int sessionId, @Nullable AutofillId[] trackedIds,
boolean saveOnAllViewsInvisible, boolean saveOnFinish,
@Nullable AutofillId[] fillableIds, @Nullable AutofillId saveTriggerId) {
+ if (saveTriggerId != null) {
+ saveTriggerId.resetSessionId();
+ }
synchronized (mLock) {
if (sVerbose) {
Log.v(TAG, "setTrackedViews(): sessionId=" + sessionId
@@ -2202,6 +2242,7 @@
mFillableIds = new ArraySet<>(fillableIds.length);
}
for (AutofillId id : fillableIds) {
+ id.resetSessionId();
mFillableIds.add(id);
}
}
@@ -2264,6 +2305,11 @@
* session when they're entered.
*/
private void setSessionFinished(int newState, @Nullable List<AutofillId> autofillableIds) {
+ if (autofillableIds != null) {
+ for (int i = 0; i < autofillableIds.size(); i++) {
+ autofillableIds.get(i).resetSessionId();
+ }
+ }
synchronized (mLock) {
if (sVerbose) {
Log.v(TAG, "setSessionFinished(): from " + getStateAsStringLocked() + " to "
@@ -2380,7 +2426,7 @@
}
}
- if (sessionFinishedState != 0) {
+ if (sessionFinishedState != STATE_UNKNOWN) {
// Callback call was "hijacked" to also update the session state.
setSessionFinished(sessionFinishedState, /* autofillableIds= */ null);
}
@@ -2879,6 +2925,7 @@
final int numIds = trackedIds.length;
for (int i = 0; i < numIds; i++) {
final AutofillId id = trackedIds[i];
+ id.resetSessionId();
if (isVisible[i]) {
mVisibleTrackedIds = addToSet(mVisibleTrackedIds, id);
@@ -3201,7 +3248,12 @@
final AutofillManager afm = mAfm.get();
if (afm == null) return null;
- final View view = afm.getClient().autofillClientFindViewByAutofillIdTraversal(id);
+ final AutofillClient client = afm.getClient();
+ if (client == null) {
+ Log.w(TAG, "getViewCoordinates(" + id + "): no autofill client");
+ return null;
+ }
+ final View view = client.autofillClientFindViewByAutofillIdTraversal(id);
if (view == null) {
Log.w(TAG, "getViewCoordinates(" + id + "): could not find view");
return null;
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 8460840..e3c2bd1 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -37,6 +37,7 @@
import android.util.Log;
import android.view.View;
import android.view.ViewStructure;
+import android.view.WindowManager;
import android.view.contentcapture.ContentCaptureSession.FlushReason;
import com.android.internal.annotations.GuardedBy;
@@ -343,10 +344,9 @@
/** @hide */
@UiThread
public void onActivityCreated(@NonNull IBinder applicationToken,
- @NonNull ComponentName activityComponent, int flags) {
+ @NonNull ComponentName activityComponent) {
if (mOptions.lite) return;
synchronized (mLock) {
- mFlags |= flags;
getMainContentCaptureSession().start(applicationToken, activityComponent, mFlags);
}
}
@@ -499,6 +499,32 @@
}
/**
+ * Called by apps to update flag secure when window attributes change.
+ *
+ * @hide
+ */
+ public void updateWindowAttributes(@NonNull WindowManager.LayoutParams params) {
+ if (sDebug) {
+ Log.d(TAG, "updateWindowAttributes(): window flags=" + params.flags);
+ }
+ final boolean flagSecureEnabled =
+ (params.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0;
+
+ MainContentCaptureSession mainSession;
+ synchronized (mLock) {
+ if (flagSecureEnabled) {
+ mFlags |= ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE;
+ } else {
+ mFlags &= ~ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE;
+ }
+ mainSession = mMainSession;
+ }
+ if (mainSession != null) {
+ mainSession.setDisabled(flagSecureEnabled);
+ }
+ }
+
+ /**
* Gets whether content capture is enabled for the given user.
*
* <p>This method is typically used by the content capture service settings page, so it can
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 8673fbe..7241664 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -593,7 +593,7 @@
}
/**
- * Called by ContentCaptureManager.setContentCaptureEnabled
+ * Sets the disabled state of content capture.
*
* @return whether disabled state was changed.
*/
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
index ee5b3ec..21ead4c 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfo.java
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -17,6 +17,7 @@
package android.view.inputmethod;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.os.Parcel;
@@ -388,7 +389,7 @@
"required when positional parameters are specified.");
}
}
- return new CursorAnchorInfo(this);
+ return CursorAnchorInfo.create(this);
}
/**
@@ -412,30 +413,90 @@
}
}
- private CursorAnchorInfo(final Builder builder) {
- mSelectionStart = builder.mSelectionStart;
- mSelectionEnd = builder.mSelectionEnd;
- mComposingTextStart = builder.mComposingTextStart;
- mComposingText = builder.mComposingText;
- mInsertionMarkerFlags = builder.mInsertionMarkerFlags;
- mInsertionMarkerHorizontal = builder.mInsertionMarkerHorizontal;
- mInsertionMarkerTop = builder.mInsertionMarkerTop;
- mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
- mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
- mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ?
- builder.mCharacterBoundsArrayBuilder.build() : null;
- mMatrixValues = new float[9];
+ private static CursorAnchorInfo create(Builder builder) {
+ final SparseRectFArray characterBoundsArray =
+ builder.mCharacterBoundsArrayBuilder != null
+ ? builder.mCharacterBoundsArrayBuilder.build()
+ : null;
+ final float[] matrixValues = new float[9];
if (builder.mMatrixInitialized) {
- System.arraycopy(builder.mMatrixValues, 0, mMatrixValues, 0, 9);
+ System.arraycopy(builder.mMatrixValues, 0, matrixValues, 0, 9);
} else {
- Matrix.IDENTITY_MATRIX.getValues(mMatrixValues);
+ Matrix.IDENTITY_MATRIX.getValues(matrixValues);
}
+ return new CursorAnchorInfo(builder.mSelectionStart, builder.mSelectionEnd,
+ builder.mComposingTextStart, builder.mComposingText, builder.mInsertionMarkerFlags,
+ builder.mInsertionMarkerHorizontal, builder.mInsertionMarkerTop,
+ builder.mInsertionMarkerBaseline, builder.mInsertionMarkerBottom,
+ characterBoundsArray, matrixValues);
+ }
+
+ private CursorAnchorInfo(int selectionStart, int selectionEnd, int composingTextStart,
+ @Nullable CharSequence composingText, int insertionMarkerFlags,
+ float insertionMarkerHorizontal, float insertionMarkerTop,
+ float insertionMarkerBaseline, float insertionMarkerBottom,
+ @Nullable SparseRectFArray characterBoundsArray, @NonNull float[] matrixValues) {
+ mSelectionStart = selectionStart;
+ mSelectionEnd = selectionEnd;
+ mComposingTextStart = composingTextStart;
+ mComposingText = composingText;
+ mInsertionMarkerFlags = insertionMarkerFlags;
+ mInsertionMarkerHorizontal = insertionMarkerHorizontal;
+ mInsertionMarkerTop = insertionMarkerTop;
+ mInsertionMarkerBaseline = insertionMarkerBaseline;
+ mInsertionMarkerBottom = insertionMarkerBottom;
+ mCharacterBoundsArray = characterBoundsArray;
+ mMatrixValues = matrixValues;
+
// To keep hash function simple, we only use some complex objects for hash.
- int hash = Objects.hashCode(mComposingText);
- hash *= 31;
- hash += Arrays.hashCode(mMatrixValues);
- mHashCode = hash;
+ int hashCode = Objects.hashCode(mComposingText);
+ hashCode *= 31;
+ hashCode += Arrays.hashCode(matrixValues);
+ mHashCode = hashCode;
+ }
+
+ /**
+ * Creates a new instance of {@link CursorAnchorInfo} by applying {@code parentMatrix} to
+ * the coordinate transformation matrix.
+ *
+ * @param original {@link CursorAnchorInfo} to be cloned from.
+ * @param parentMatrix {@link Matrix} to be applied to {@code original.getMatrix()}
+ * @return A new instance of {@link CursorAnchorInfo} whose {@link CursorAnchorInfo#getMatrix()}
+ * returns {@code parentMatrix * original.getMatrix()}.
+ * @hide
+ */
+ public static CursorAnchorInfo createForAdditionalParentMatrix(CursorAnchorInfo original,
+ @NonNull Matrix parentMatrix) {
+ return new CursorAnchorInfo(original.mSelectionStart, original.mSelectionEnd,
+ original.mComposingTextStart, original.mComposingText,
+ original.mInsertionMarkerFlags, original.mInsertionMarkerHorizontal,
+ original.mInsertionMarkerTop, original.mInsertionMarkerBaseline,
+ original.mInsertionMarkerBottom, original.mCharacterBoundsArray,
+ computeMatrixValues(parentMatrix, original));
+ }
+
+ /**
+ * Returns a float array that represents {@link Matrix} elements for
+ * {@code parentMatrix * info.getMatrix()}.
+ *
+ * @param parentMatrix {@link Matrix} to be multiplied.
+ * @param info {@link CursorAnchorInfo} to provide {@link Matrix} to be multiplied.
+ * @return {@code parentMatrix * info.getMatrix()}.
+ */
+ private static float[] computeMatrixValues(@NonNull Matrix parentMatrix,
+ @NonNull CursorAnchorInfo info) {
+ if (parentMatrix.isIdentity()) {
+ return info.mMatrixValues;
+ }
+
+ final Matrix newMatrix = new Matrix();
+ newMatrix.setValues(info.mMatrixValues);
+ newMatrix.postConcat(parentMatrix);
+
+ final float[] matrixValues = new float[9];
+ newMatrix.getValues(matrixValues);
+ return matrixValues;
}
/**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index fd73856..d302c2b 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -33,6 +33,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.graphics.Matrix;
import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
import android.os.Binder;
@@ -425,6 +426,17 @@
*/
private CursorAnchorInfo mCursorAnchorInfo = null;
+ /**
+ * A special {@link Matrix} that can be provided by the system when this instance is running
+ * inside a virtual display that is managed by {@link android.app.ActivityView}.
+ *
+ * <p>If this is non-{@code null}, {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}
+ * should be adjusted with this {@link Matrix}.</p>
+ *
+ * <p>{@code null} when not used.</p>
+ */
+ private Matrix mActivityViewToScreenMatrix = null;
+
// -----------------------------------------------------------
/**
@@ -473,6 +485,7 @@
static final int MSG_REPORT_FULLSCREEN_MODE = 10;
static final int MSG_REPORT_PRE_RENDERED = 15;
static final int MSG_APPLY_IME_VISIBILITY = 20;
+ static final int MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX = 30;
private static boolean isAutofillUIShowing(View servedView) {
AutofillManager afm = servedView.getContext().getSystemService(AutofillManager.class);
@@ -510,7 +523,7 @@
return null;
}
final InputMethodManager fallbackImm =
- viewRootImpl.mDisplayContext.getSystemService(InputMethodManager.class);
+ viewRootImpl.mContext.getSystemService(InputMethodManager.class);
if (fallbackImm == null) {
Log.e(TAG, "b/117267690: Failed to get non-null fallback IMM. view=" + view);
return null;
@@ -579,6 +592,7 @@
mCurMethod = res.method;
mCurId = res.id;
mBindSequence = res.sequence;
+ mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix();
}
startInputInner(StartInputReason.BOUND_TO_IMMS, null, 0, 0, 0);
return;
@@ -686,6 +700,48 @@
}
return;
}
+ case MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX: {
+ final float[] matrixValues = (float[]) msg.obj;
+ final int bindSequence = msg.arg1;
+ synchronized (mH) {
+ if (mBindSequence != bindSequence) {
+ return;
+ }
+ if (matrixValues == null) {
+ // That this app is unbound from the parent ActivityView. In this case,
+ // calling updateCursorAnchorInfo() isn't safe. Only clear the matrix.
+ mActivityViewToScreenMatrix = null;
+ return;
+ }
+
+ final float[] currentValues = new float[9];
+ mActivityViewToScreenMatrix.getValues(currentValues);
+ if (Arrays.equals(currentValues, matrixValues)) {
+ return;
+ }
+ mActivityViewToScreenMatrix.setValues(matrixValues);
+
+ if (mCursorAnchorInfo == null || mCurMethod == null
+ || mServedInputConnectionWrapper == null) {
+ return;
+ }
+ final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode
+ & InputConnection.CURSOR_UPDATE_MONITOR) != 0;
+ if (!isMonitoring) {
+ return;
+ }
+ // Since the host ActivityView is moved, we need to issue
+ // IMS#updateCursorAnchorInfo() again.
+ try {
+ mCurMethod.updateCursorAnchorInfo(
+ CursorAnchorInfo.createForAdditionalParentMatrix(
+ mCursorAnchorInfo, mActivityViewToScreenMatrix));
+ } catch (RemoteException e) {
+ Log.w(TAG, "IME died: " + mCurId, e);
+ }
+ }
+ return;
+ }
}
}
}
@@ -777,6 +833,11 @@
.sendToTarget();
}
+ @Override
+ public void updateActivityViewToScreenMatrix(int bindSequence, float[] matrixValues) {
+ mH.obtainMessage(MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX, bindSequence, 0,
+ matrixValues).sendToTarget();
+ }
};
final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
@@ -1192,6 +1253,7 @@
@UnsupportedAppUsage
void finishInputLocked() {
mNextServedView = null;
+ mActivityViewToScreenMatrix = null;
if (mServedView != null) {
if (DEBUG) Log.v(TAG, "FINISH INPUT: mServedView=" + dumpViewInfo(mServedView));
mServedView = null;
@@ -1668,6 +1730,7 @@
+ InputMethodDebug.startInputFlagsToString(startInputFlags));
return false;
}
+ mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix();
if (res.id != null) {
setInputChannelLocked(res.channel);
mBindSequence = res.sequence;
@@ -2200,7 +2263,13 @@
}
if (DEBUG) Log.v(TAG, "updateCursorAnchorInfo: " + cursorAnchorInfo);
try {
- mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
+ if (mActivityViewToScreenMatrix != null) {
+ mCurMethod.updateCursorAnchorInfo(
+ CursorAnchorInfo.createForAdditionalParentMatrix(
+ cursorAnchorInfo, mActivityViewToScreenMatrix));
+ } else {
+ mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
+ }
mCursorAnchorInfo = cursorAnchorInfo;
// Clear immediate bit (if any).
mRequestUpdateCursorAnchorInfoMonitorMode &=
@@ -2779,6 +2848,30 @@
}
/**
+ * An internal API for {@link android.app.ActivityView} to report where its embedded virtual
+ * display is placed.
+ *
+ * @param childDisplayId Display ID of the embedded virtual display.
+ * @param matrix {@link Matrix} to convert virtual display screen coordinates to
+ * the host screen coordinates. {@code null} to clear the relationship.
+ * @hide
+ */
+ public void reportActivityView(int childDisplayId, @Nullable Matrix matrix) {
+ try {
+ final float[] matrixValues;
+ if (matrix == null) {
+ matrixValues = null;
+ } else {
+ matrixValues = new float[9];
+ matrix.getValues(matrixValues);
+ }
+ mService.reportActivityView(mClient, childDisplayId, matrixValues);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Force switch to the last used input method and subtype. If the last input method didn't have
* any subtypes, the framework will simply switch to the last input method with no subtype
* specified.
@@ -2887,6 +2980,16 @@
}
}
+ /**
+ * <p>This is used for CTS test only. Do not use this method outside of CTS package.<p/>
+ * @return the ID of this display which this {@link InputMethodManager} resides
+ * @hide
+ */
+ @TestApi
+ public int getDisplayId() {
+ return mDisplayId;
+ }
+
void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
final Printer p = new PrintWriterPrinter(fout);
p.println("Input method client state for " + this + ":");
diff --git a/core/java/android/view/textclassifier/ConfigParser.java b/core/java/android/view/textclassifier/ConfigParser.java
index b475412..63de059 100644
--- a/core/java/android/view/textclassifier/ConfigParser.java
+++ b/core/java/android/view/textclassifier/ConfigParser.java
@@ -17,9 +17,19 @@
import android.annotation.Nullable;
import android.provider.DeviceConfig;
+import android.util.ArrayMap;
import android.util.KeyValueListParser;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
/**
* Retrieves settings from {@link DeviceConfig} and {@link android.provider.Settings}.
@@ -27,80 +37,228 @@
*
* @hide
*/
-@VisibleForTesting
+@VisibleForTesting(visibility = Visibility.PACKAGE)
public final class ConfigParser {
private static final String TAG = "ConfigParser";
- private final KeyValueListParser mParser;
+ static final boolean ENABLE_DEVICE_CONFIG = true;
- // TODO: Re-enable DeviceConfig when it has reasonable performance or just delete the
- // option of using DeviceConfig entirely.
- static final boolean ENABLE_DEVICE_CONFIG = false;
+ private static final String STRING_LIST_DELIMITER = ":";
- public ConfigParser(@Nullable String textClassifierConstants) {
- final KeyValueListParser parser = new KeyValueListParser(',');
- try {
- parser.setString(textClassifierConstants);
- } catch (IllegalArgumentException e) {
- // Failed to parse the settings string, log this and move on with defaults.
- Log.w(TAG, "Bad text_classifier_constants: " + textClassifierConstants);
+ private final Supplier<String> mLegacySettingsSupplier;
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private final Map<String, Object> mCache = new ArrayMap<>();
+ @GuardedBy("mLock")
+ private @Nullable KeyValueListParser mSettingsParser; // Call getLegacySettings() instead.
+
+ public ConfigParser(Supplier<String> legacySettingsSupplier) {
+ mLegacySettingsSupplier = Preconditions.checkNotNull(legacySettingsSupplier);
+ }
+
+ private KeyValueListParser getLegacySettings() {
+ synchronized (mLock) {
+ if (mSettingsParser == null) {
+ final String legacySettings = mLegacySettingsSupplier.get();
+ try {
+ mSettingsParser = new KeyValueListParser(',');
+ mSettingsParser.setString(legacySettings);
+ } catch (IllegalArgumentException e) {
+ // Failed to parse the settings string, log this and move on with defaults.
+ Log.w(TAG, "Bad text_classifier_constants: " + legacySettings);
+ }
+ }
+ return mSettingsParser;
}
- mParser = parser;
}
/**
- * Reads a boolean flag.
+ * Reads a boolean setting through the cache.
*/
public boolean getBoolean(String key, boolean defaultValue) {
- if (ENABLE_DEVICE_CONFIG) {
- return DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
- key,
- mParser.getBoolean(key, defaultValue));
- } else {
- return mParser.getBoolean(key, defaultValue);
+ synchronized (mLock) {
+ final Object cached = mCache.get(key);
+ if (cached instanceof Boolean) {
+ return (boolean) cached;
+ }
+ final boolean value;
+ if (ENABLE_DEVICE_CONFIG) {
+ value = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+ key,
+ getLegacySettings().getBoolean(key, defaultValue));
+ } else {
+ value = getLegacySettings().getBoolean(key, defaultValue);
+ }
+ mCache.put(key, value);
+ return value;
}
}
/**
- * Reads an integer flag.
+ * Reads an integer setting through the cache.
*/
public int getInt(String key, int defaultValue) {
- if (ENABLE_DEVICE_CONFIG) {
- return DeviceConfig.getInt(
- DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
- key,
- mParser.getInt(key, defaultValue));
- } else {
- return mParser.getInt(key, defaultValue);
+ synchronized (mLock) {
+ final Object cached = mCache.get(key);
+ if (cached instanceof Integer) {
+ return (int) cached;
+ }
+ final int value;
+ if (ENABLE_DEVICE_CONFIG) {
+ value = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+ key,
+ getLegacySettings().getInt(key, defaultValue));
+ } else {
+ value = getLegacySettings().getInt(key, defaultValue);
+ }
+ mCache.put(key, value);
+ return value;
}
}
/**
- * Reads a float flag.
+ * Reads a float setting through the cache.
*/
public float getFloat(String key, float defaultValue) {
- if (ENABLE_DEVICE_CONFIG) {
- return DeviceConfig.getFloat(
- DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
- key,
- mParser.getFloat(key, defaultValue));
- } else {
- return mParser.getFloat(key, defaultValue);
+ synchronized (mLock) {
+ final Object cached = mCache.get(key);
+ if (cached instanceof Float) {
+ return (float) cached;
+ }
+ final float value;
+ if (ENABLE_DEVICE_CONFIG) {
+ value = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+ key,
+ getLegacySettings().getFloat(key, defaultValue));
+ } else {
+ value = getLegacySettings().getFloat(key, defaultValue);
+ }
+ mCache.put(key, value);
+ return value;
}
}
/**
- * Reads a string flag.
+ * Reads a string setting through the cache.
*/
public String getString(String key, String defaultValue) {
- if (ENABLE_DEVICE_CONFIG) {
- return DeviceConfig.getString(
- DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
- key,
- mParser.getString(key, defaultValue));
+ synchronized (mLock) {
+ final Object cached = mCache.get(key);
+ if (cached instanceof String) {
+ return (String) cached;
+ }
+ final String value;
+ if (ENABLE_DEVICE_CONFIG) {
+ value = DeviceConfig.getString(
+ DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+ key,
+ getLegacySettings().getString(key, defaultValue));
+ } else {
+ value = getLegacySettings().getString(key, defaultValue);
+ }
+ mCache.put(key, value);
+ return value;
+ }
+ }
+
+ /**
+ * Reads a string list setting through the cache.
+ */
+ public List<String> getStringList(String key, List<String> defaultValue) {
+ synchronized (mLock) {
+ final Object cached = mCache.get(key);
+ if (cached instanceof List) {
+ final List asList = (List) cached;
+ if (asList.isEmpty()) {
+ return Collections.emptyList();
+ } else if (asList.get(0) instanceof String) {
+ return (List<String>) cached;
+ }
+ }
+ final List<String> value;
+ if (ENABLE_DEVICE_CONFIG) {
+ value = getDeviceConfigStringList(
+ key,
+ getSettingsStringList(key, defaultValue));
+ } else {
+ value = getSettingsStringList(key, defaultValue);
+ }
+ mCache.put(key, value);
+ return value;
+ }
+ }
+
+ /**
+ * Reads a float array through the cache. The returned array should be expected to be of the
+ * same length as that of the defaultValue.
+ */
+ public float[] getFloatArray(String key, float[] defaultValue) {
+ synchronized (mLock) {
+ final Object cached = mCache.get(key);
+ if (cached instanceof float[]) {
+ return (float[]) cached;
+ }
+ final float[] value;
+ if (ENABLE_DEVICE_CONFIG) {
+ value = getDeviceConfigFloatArray(
+ key,
+ getSettingsFloatArray(key, defaultValue));
+ } else {
+ value = getSettingsFloatArray(key, defaultValue);
+ }
+ mCache.put(key, value);
+ return value;
+ }
+ }
+
+ private List<String> getSettingsStringList(String key, List<String> defaultValue) {
+ return parse(mSettingsParser.getString(key, null), defaultValue);
+ }
+
+ private static List<String> getDeviceConfigStringList(String key, List<String> defaultValue) {
+ return parse(
+ DeviceConfig.getString(DeviceConfig.NAMESPACE_TEXTCLASSIFIER, key, null),
+ defaultValue);
+ }
+
+ private static float[] getDeviceConfigFloatArray(String key, float[] defaultValue) {
+ return parse(
+ DeviceConfig.getString(DeviceConfig.NAMESPACE_TEXTCLASSIFIER, key, null),
+ defaultValue);
+ }
+
+ private float[] getSettingsFloatArray(String key, float[] defaultValue) {
+ return parse(mSettingsParser.getString(key, null), defaultValue);
+ }
+
+ private static List<String> parse(@Nullable String listStr, List<String> defaultValue) {
+ if (listStr != null) {
+ return Collections.unmodifiableList(
+ Arrays.asList(listStr.split(STRING_LIST_DELIMITER)));
+ }
+ return defaultValue;
+ }
+
+ private static float[] parse(@Nullable String arrayStr, float[] defaultValue) {
+ if (arrayStr != null) {
+ final String[] split = arrayStr.split(STRING_LIST_DELIMITER);
+ if (split.length != defaultValue.length) {
+ return defaultValue;
+ }
+ final float[] result = new float[split.length];
+ for (int i = 0; i < split.length; i++) {
+ try {
+ result[i] = Float.parseFloat(split[i]);
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+ return result;
} else {
- return mParser.getString(key, defaultValue);
+ return defaultValue;
}
}
}
diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java
index 876e5cc..2964f51 100644
--- a/core/java/android/view/textclassifier/TextClassificationConstants.java
+++ b/core/java/android/view/textclassifier/TextClassificationConstants.java
@@ -16,58 +16,39 @@
package android.view.textclassifier;
-import android.annotation.Nullable;
-
import com.android.internal.util.IndentingPrintWriter;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
-import java.util.StringJoiner;
+import java.util.function.Supplier;
/**
* TextClassifier specific settings.
- * This is encoded as a key=value list, separated by commas. Ex:
- *
- * <pre>
- * smart_linkify_enabled (boolean)
- * system_textclassifier_enabled (boolean)
- * model_dark_launch_enabled (boolean)
- * smart_selection_enabled (boolean)
- * smart_text_share_enabled (boolean)
- * smart_linkify_enabled (boolean)
- * smart_select_animation_enabled (boolean)
- * suggest_selection_max_range_length (int)
- * classify_text_max_range_length (int)
- * generate_links_max_text_length (int)
- * generate_links_log_sample_rate (int)
- * entity_list_default (String[])
- * entity_list_not_editable (String[])
- * entity_list_editable (String[])
- * in_app_conversation_action_types_default (String[])
- * notification_conversation_action_types_default (String[])
- * lang_id_threshold_override (float)
- * template_intent_factory_enabled (boolean)
- * translate_in_classification_enabled (boolean)
- * detect_languages_from_text_enabled (boolean)
- * lang_id_context_settings (float[])
- * </pre>
- *
+ * This is encoded as a key=value list, separated by commas.
* <p>
- * Type: string
- * see also android.provider.Settings.Global.TEXT_CLASSIFIER_CONSTANTS
- *
* Example of setting the values for testing.
+ * <p>
+ * <pre>
* adb shell settings put global text_classifier_constants \
* model_dark_launch_enabled=true,smart_selection_enabled=true, \
* entity_list_default=phone:address, \
* lang_id_context_settings=20:1.0:0.4
+ * </pre>
+ * <p>
+ * Settings are also available in device config. These take precedence over those in settings
+ * global.
+ * <p>
+ * <pre>
+ * adb shell cmd device_config put textclassifier system_textclassifier_enabled true
+ * </pre>
+ *
+ * @see android.provider.Settings.Global.TEXT_CLASSIFIER_CONSTANTS
+ * @see android.provider.DeviceConfig.NAMESPACE_TEXTCLASSIFIER
* @hide
*/
+// TODO: Rename to TextClassifierSettings.
public final class TextClassificationConstants {
- private static final String LOG_TAG = TextClassifier.DEFAULT_LOG_TAG;
-
/**
* Whether the smart linkify feature is enabled.
*/
@@ -188,29 +169,26 @@
private static final int CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT = 10 * 1000;
private static final int GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT = 100 * 1000;
private static final int GENERATE_LINKS_LOG_SAMPLE_RATE_DEFAULT = 100;
- private static final String STRING_LIST_DELIMITER = ":";
- private static final String ENTITY_LIST_DEFAULT_VALUE = new StringJoiner(STRING_LIST_DELIMITER)
- .add(TextClassifier.TYPE_ADDRESS)
- .add(TextClassifier.TYPE_EMAIL)
- .add(TextClassifier.TYPE_PHONE)
- .add(TextClassifier.TYPE_URL)
- .add(TextClassifier.TYPE_DATE)
- .add(TextClassifier.TYPE_DATE_TIME)
- .add(TextClassifier.TYPE_FLIGHT_NUMBER).toString();
- private static final String CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES =
- new StringJoiner(STRING_LIST_DELIMITER)
- .add(ConversationAction.TYPE_TEXT_REPLY)
- .add(ConversationAction.TYPE_CREATE_REMINDER)
- .add(ConversationAction.TYPE_CALL_PHONE)
- .add(ConversationAction.TYPE_OPEN_URL)
- .add(ConversationAction.TYPE_SEND_EMAIL)
- .add(ConversationAction.TYPE_SEND_SMS)
- .add(ConversationAction.TYPE_TRACK_FLIGHT)
- .add(ConversationAction.TYPE_VIEW_CALENDAR)
- .add(ConversationAction.TYPE_VIEW_MAP)
- .add(ConversationAction.TYPE_ADD_CONTACT)
- .add(ConversationAction.TYPE_COPY)
- .toString();
+ private static final List<String> ENTITY_LIST_DEFAULT_VALUE = Arrays.asList(
+ TextClassifier.TYPE_ADDRESS,
+ TextClassifier.TYPE_EMAIL,
+ TextClassifier.TYPE_PHONE,
+ TextClassifier.TYPE_URL,
+ TextClassifier.TYPE_DATE,
+ TextClassifier.TYPE_DATE_TIME,
+ TextClassifier.TYPE_FLIGHT_NUMBER);
+ private static final List<String> CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES = Arrays.asList(
+ ConversationAction.TYPE_TEXT_REPLY,
+ ConversationAction.TYPE_CREATE_REMINDER,
+ ConversationAction.TYPE_CALL_PHONE,
+ ConversationAction.TYPE_OPEN_URL,
+ ConversationAction.TYPE_SEND_EMAIL,
+ ConversationAction.TYPE_SEND_SMS,
+ ConversationAction.TYPE_TRACK_FLIGHT,
+ ConversationAction.TYPE_VIEW_CALENDAR,
+ ConversationAction.TYPE_VIEW_MAP,
+ ConversationAction.TYPE_ADD_CONTACT,
+ ConversationAction.TYPE_COPY);
/**
* < 0 : Not set. Use value from LangId model.
* 0 - 1: Override value in LangId model.
@@ -221,259 +199,185 @@
private static final boolean TEMPLATE_INTENT_FACTORY_ENABLED_DEFAULT = true;
private static final boolean TRANSLATE_IN_CLASSIFICATION_ENABLED_DEFAULT = true;
private static final boolean DETECT_LANGUAGES_FROM_TEXT_ENABLED_DEFAULT = true;
- private static final String LANG_ID_CONTEXT_SETTINGS_DEFAULT =
- new StringJoiner(STRING_LIST_DELIMITER).add("20").add("1.0").add("0.4").toString();
+ private static final float[] LANG_ID_CONTEXT_SETTINGS_DEFAULT = new float[] {20f, 1.0f, 0.4f};
- private final boolean mSystemTextClassifierEnabled;
- private final boolean mLocalTextClassifierEnabled;
- private final boolean mModelDarkLaunchEnabled;
- private final boolean mSmartSelectionEnabled;
- private final boolean mSmartTextShareEnabled;
- private final boolean mSmartLinkifyEnabled;
- private final boolean mSmartSelectionAnimationEnabled;
- private final int mSuggestSelectionMaxRangeLength;
- private final int mClassifyTextMaxRangeLength;
- private final int mGenerateLinksMaxTextLength;
- private final int mGenerateLinksLogSampleRate;
- private final List<String> mEntityListDefault;
- private final List<String> mEntityListNotEditable;
- private final List<String> mEntityListEditable;
- private final List<String> mInAppConversationActionTypesDefault;
- private final List<String> mNotificationConversationActionTypesDefault;
- private final float mLangIdThresholdOverride;
- private final boolean mTemplateIntentFactoryEnabled;
- private final boolean mTranslateInClassificationEnabled;
- private final boolean mDetectLanguagesFromTextEnabled;
- private final float[] mLangIdContextSettings;
+ private final ConfigParser mConfigParser;
- private TextClassificationConstants(@Nullable String settings) {
- ConfigParser configParser = new ConfigParser(settings);
- mSystemTextClassifierEnabled =
- configParser.getBoolean(
- SYSTEM_TEXT_CLASSIFIER_ENABLED,
- SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT);
- mLocalTextClassifierEnabled =
- configParser.getBoolean(
- LOCAL_TEXT_CLASSIFIER_ENABLED,
- LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT);
- mModelDarkLaunchEnabled =
- configParser.getBoolean(
- MODEL_DARK_LAUNCH_ENABLED,
- MODEL_DARK_LAUNCH_ENABLED_DEFAULT);
- mSmartSelectionEnabled =
- configParser.getBoolean(
- SMART_SELECTION_ENABLED,
- SMART_SELECTION_ENABLED_DEFAULT);
- mSmartTextShareEnabled =
- configParser.getBoolean(
- SMART_TEXT_SHARE_ENABLED,
- SMART_TEXT_SHARE_ENABLED_DEFAULT);
- mSmartLinkifyEnabled =
- configParser.getBoolean(
- SMART_LINKIFY_ENABLED,
- SMART_LINKIFY_ENABLED_DEFAULT);
- mSmartSelectionAnimationEnabled =
- configParser.getBoolean(
- SMART_SELECT_ANIMATION_ENABLED,
- SMART_SELECT_ANIMATION_ENABLED_DEFAULT);
- mSuggestSelectionMaxRangeLength =
- configParser.getInt(
- SUGGEST_SELECTION_MAX_RANGE_LENGTH,
- SUGGEST_SELECTION_MAX_RANGE_LENGTH_DEFAULT);
- mClassifyTextMaxRangeLength =
- configParser.getInt(
- CLASSIFY_TEXT_MAX_RANGE_LENGTH,
- CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT);
- mGenerateLinksMaxTextLength =
- configParser.getInt(
- GENERATE_LINKS_MAX_TEXT_LENGTH,
- GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT);
- mGenerateLinksLogSampleRate =
- configParser.getInt(
- GENERATE_LINKS_LOG_SAMPLE_RATE,
- GENERATE_LINKS_LOG_SAMPLE_RATE_DEFAULT);
- mEntityListDefault = parseStringList(
- configParser.getString(
- ENTITY_LIST_DEFAULT,
- ENTITY_LIST_DEFAULT_VALUE));
- mEntityListNotEditable = parseStringList(
- configParser.getString(
- ENTITY_LIST_NOT_EDITABLE,
- ENTITY_LIST_DEFAULT_VALUE));
- mEntityListEditable = parseStringList(
- configParser.getString(
- ENTITY_LIST_EDITABLE,
- ENTITY_LIST_DEFAULT_VALUE));
- mInAppConversationActionTypesDefault = parseStringList(
- configParser.getString(
- IN_APP_CONVERSATION_ACTION_TYPES_DEFAULT,
- CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES));
- mNotificationConversationActionTypesDefault = parseStringList(
- configParser.getString(
- NOTIFICATION_CONVERSATION_ACTION_TYPES_DEFAULT,
- CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES));
- mLangIdThresholdOverride =
- configParser.getFloat(
- LANG_ID_THRESHOLD_OVERRIDE,
- LANG_ID_THRESHOLD_OVERRIDE_DEFAULT);
- mTemplateIntentFactoryEnabled =
- configParser.getBoolean(
- TEMPLATE_INTENT_FACTORY_ENABLED,
- TEMPLATE_INTENT_FACTORY_ENABLED_DEFAULT);
- mTranslateInClassificationEnabled =
- configParser.getBoolean(
- TRANSLATE_IN_CLASSIFICATION_ENABLED,
- TRANSLATE_IN_CLASSIFICATION_ENABLED_DEFAULT);
- mDetectLanguagesFromTextEnabled =
- configParser.getBoolean(
- DETECT_LANGUAGES_FROM_TEXT_ENABLED,
- DETECT_LANGUAGES_FROM_TEXT_ENABLED_DEFAULT);
- mLangIdContextSettings = parseFloatArray(
- configParser,
- LANG_ID_CONTEXT_SETTINGS,
- LANG_ID_CONTEXT_SETTINGS_DEFAULT);
- }
-
- /** Load from a settings string. */
- public static TextClassificationConstants loadFromString(String settings) {
- return new TextClassificationConstants(settings);
+ public TextClassificationConstants(Supplier<String> legacySettingsSupplier) {
+ mConfigParser = new ConfigParser(legacySettingsSupplier);
}
public boolean isLocalTextClassifierEnabled() {
- return mLocalTextClassifierEnabled;
+ return mConfigParser.getBoolean(
+ LOCAL_TEXT_CLASSIFIER_ENABLED,
+ LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT);
}
public boolean isSystemTextClassifierEnabled() {
- return mSystemTextClassifierEnabled;
+ return mConfigParser.getBoolean(
+ SYSTEM_TEXT_CLASSIFIER_ENABLED,
+ SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT);
}
public boolean isModelDarkLaunchEnabled() {
- return mModelDarkLaunchEnabled;
+ return mConfigParser.getBoolean(
+ MODEL_DARK_LAUNCH_ENABLED,
+ MODEL_DARK_LAUNCH_ENABLED_DEFAULT);
}
public boolean isSmartSelectionEnabled() {
- return mSmartSelectionEnabled;
+ return mConfigParser.getBoolean(
+ SMART_SELECTION_ENABLED,
+ SMART_SELECTION_ENABLED_DEFAULT);
}
public boolean isSmartTextShareEnabled() {
- return mSmartTextShareEnabled;
+ return mConfigParser.getBoolean(
+ SMART_TEXT_SHARE_ENABLED,
+ SMART_TEXT_SHARE_ENABLED_DEFAULT);
}
public boolean isSmartLinkifyEnabled() {
- return mSmartLinkifyEnabled;
+ return mConfigParser.getBoolean(
+ SMART_LINKIFY_ENABLED,
+ SMART_LINKIFY_ENABLED_DEFAULT);
}
public boolean isSmartSelectionAnimationEnabled() {
- return mSmartSelectionAnimationEnabled;
+ return mConfigParser.getBoolean(
+ SMART_SELECT_ANIMATION_ENABLED,
+ SMART_SELECT_ANIMATION_ENABLED_DEFAULT);
}
public int getSuggestSelectionMaxRangeLength() {
- return mSuggestSelectionMaxRangeLength;
+ return mConfigParser.getInt(
+ SUGGEST_SELECTION_MAX_RANGE_LENGTH,
+ SUGGEST_SELECTION_MAX_RANGE_LENGTH_DEFAULT);
}
public int getClassifyTextMaxRangeLength() {
- return mClassifyTextMaxRangeLength;
+ return mConfigParser.getInt(
+ CLASSIFY_TEXT_MAX_RANGE_LENGTH,
+ CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT);
}
public int getGenerateLinksMaxTextLength() {
- return mGenerateLinksMaxTextLength;
+ return mConfigParser.getInt(
+ GENERATE_LINKS_MAX_TEXT_LENGTH,
+ GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT);
}
public int getGenerateLinksLogSampleRate() {
- return mGenerateLinksLogSampleRate;
+ return mConfigParser.getInt(
+ GENERATE_LINKS_LOG_SAMPLE_RATE,
+ GENERATE_LINKS_LOG_SAMPLE_RATE_DEFAULT);
}
public List<String> getEntityListDefault() {
- return mEntityListDefault;
+ return mConfigParser.getStringList(
+ ENTITY_LIST_DEFAULT,
+ ENTITY_LIST_DEFAULT_VALUE);
}
public List<String> getEntityListNotEditable() {
- return mEntityListNotEditable;
+ return mConfigParser.getStringList(
+ ENTITY_LIST_NOT_EDITABLE,
+ ENTITY_LIST_DEFAULT_VALUE);
}
public List<String> getEntityListEditable() {
- return mEntityListEditable;
+ return mConfigParser.getStringList(
+ ENTITY_LIST_EDITABLE,
+ ENTITY_LIST_DEFAULT_VALUE);
}
public List<String> getInAppConversationActionTypes() {
- return mInAppConversationActionTypesDefault;
+ return mConfigParser.getStringList(
+ IN_APP_CONVERSATION_ACTION_TYPES_DEFAULT,
+ CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES);
}
public List<String> getNotificationConversationActionTypes() {
- return mNotificationConversationActionTypesDefault;
+ return mConfigParser.getStringList(
+ NOTIFICATION_CONVERSATION_ACTION_TYPES_DEFAULT,
+ CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES);
}
public float getLangIdThresholdOverride() {
- return mLangIdThresholdOverride;
+ return mConfigParser.getFloat(
+ LANG_ID_THRESHOLD_OVERRIDE,
+ LANG_ID_THRESHOLD_OVERRIDE_DEFAULT);
}
public boolean isTemplateIntentFactoryEnabled() {
- return mTemplateIntentFactoryEnabled;
+ return mConfigParser.getBoolean(
+ TEMPLATE_INTENT_FACTORY_ENABLED,
+ TEMPLATE_INTENT_FACTORY_ENABLED_DEFAULT);
}
public boolean isTranslateInClassificationEnabled() {
- return mTranslateInClassificationEnabled;
+ return mConfigParser.getBoolean(
+ TRANSLATE_IN_CLASSIFICATION_ENABLED,
+ TRANSLATE_IN_CLASSIFICATION_ENABLED_DEFAULT);
}
public boolean isDetectLanguagesFromTextEnabled() {
- return mDetectLanguagesFromTextEnabled;
+ return mConfigParser.getBoolean(
+ DETECT_LANGUAGES_FROM_TEXT_ENABLED,
+ DETECT_LANGUAGES_FROM_TEXT_ENABLED_DEFAULT);
}
public float[] getLangIdContextSettings() {
- return mLangIdContextSettings;
- }
-
- private static List<String> parseStringList(String listStr) {
- return Collections.unmodifiableList(Arrays.asList(listStr.split(STRING_LIST_DELIMITER)));
- }
-
- private static float[] parseFloatArray(
- ConfigParser configParser, String key, String defaultStr) {
- final String str = configParser.getString(key, defaultStr);
- final String[] defaultSplit = defaultStr.split(STRING_LIST_DELIMITER);
- String[] split = str.split(STRING_LIST_DELIMITER);
- if (split.length != defaultSplit.length) {
- Log.v(LOG_TAG, "Error parsing " + key + " flag. Using defaults.");
- split = defaultSplit;
- }
- final float[] result = new float[split.length];
- for (int i = 0; i < split.length; i++) {
- try {
- result[i] = Float.parseFloat(split[i]);
- } catch (NumberFormatException e) {
- Log.v(LOG_TAG, "Error parsing part of " + key + " flag. Using defaults.");
- result[i] = Float.parseFloat(defaultSplit[i]);
- }
- }
- return result;
+ return mConfigParser.getFloatArray(
+ LANG_ID_CONTEXT_SETTINGS,
+ LANG_ID_CONTEXT_SETTINGS_DEFAULT);
}
void dump(IndentingPrintWriter pw) {
pw.println("TextClassificationConstants:");
pw.increaseIndent();
- pw.printPair("isLocalTextClassifierEnabled", mLocalTextClassifierEnabled);
- pw.printPair("isSystemTextClassifierEnabled", mSystemTextClassifierEnabled);
- pw.printPair("isModelDarkLaunchEnabled", mModelDarkLaunchEnabled);
- pw.printPair("isSmartSelectionEnabled", mSmartSelectionEnabled);
- pw.printPair("isSmartTextShareEnabled", mSmartTextShareEnabled);
- pw.printPair("isSmartLinkifyEnabled", mSmartLinkifyEnabled);
- pw.printPair("isSmartSelectionAnimationEnabled", mSmartSelectionAnimationEnabled);
- pw.printPair("getSuggestSelectionMaxRangeLength", mSuggestSelectionMaxRangeLength);
- pw.printPair("getClassifyTextMaxRangeLength", mClassifyTextMaxRangeLength);
- pw.printPair("getGenerateLinksMaxTextLength", mGenerateLinksMaxTextLength);
- pw.printPair("getGenerateLinksLogSampleRate", mGenerateLinksLogSampleRate);
- pw.printPair("getEntityListDefault", mEntityListDefault);
- pw.printPair("getEntityListNotEditable", mEntityListNotEditable);
- pw.printPair("getEntityListEditable", mEntityListEditable);
- pw.printPair("getInAppConversationActionTypes", mInAppConversationActionTypesDefault);
- pw.printPair("getNotificationConversationActionTypes",
- mNotificationConversationActionTypesDefault);
- pw.printPair("getLangIdThresholdOverride", mLangIdThresholdOverride);
- pw.printPair("isTemplateIntentFactoryEnabled", mTemplateIntentFactoryEnabled);
- pw.printPair("isTranslateInClassificationEnabled", mTranslateInClassificationEnabled);
- pw.printPair("isDetectLanguageFromTextEnabled", mDetectLanguagesFromTextEnabled);
- pw.printPair("getLangIdContextSettings", Arrays.toString(mLangIdContextSettings));
+ pw.printPair("classify_text_max_range_length", getClassifyTextMaxRangeLength())
+ .println();
+ pw.printPair("detect_language_from_text_enabled", isDetectLanguagesFromTextEnabled())
+ .println();
+ pw.printPair("entity_list_default", getEntityListDefault())
+ .println();
+ pw.printPair("entity_list_editable", getEntityListEditable())
+ .println();
+ pw.printPair("entity_list_not_editable", getEntityListNotEditable())
+ .println();
+ pw.printPair("generate_links_log_sample_rate", getGenerateLinksLogSampleRate())
+ .println();
+ pw.printPair("generate_links_max_text_length", getGenerateLinksMaxTextLength())
+ .println();
+ pw.printPair("in_app_conversation_action_types_default", getInAppConversationActionTypes())
+ .println();
+ pw.printPair("lang_id_context_settings", Arrays.toString(getLangIdContextSettings()))
+ .println();
+ pw.printPair("lang_id_threshold_override", getLangIdThresholdOverride())
+ .println();
+ pw.printPair("local_textclassifier_enabled", isLocalTextClassifierEnabled())
+ .println();
+ pw.printPair("model_dark_launch_enabled", isModelDarkLaunchEnabled())
+ .println();
+ pw.printPair("notification_conversation_action_types_default",
+ getNotificationConversationActionTypes()).println();
+ pw.printPair("smart_linkify_enabled", isSmartLinkifyEnabled())
+ .println();
+ pw.printPair("smart_select_animation_enabled", isSmartSelectionAnimationEnabled())
+ .println();
+ pw.printPair("smart_selection_enabled", isSmartSelectionEnabled())
+ .println();
+ pw.printPair("smart_text_share_enabled", isSmartTextShareEnabled())
+ .println();
+ pw.printPair("suggest_selection_max_range_length", getSuggestSelectionMaxRangeLength())
+ .println();
+ pw.printPair("system_textclassifier_enabled", isSystemTextClassifierEnabled())
+ .println();
+ pw.printPair("template_intent_factory_enabled", isTemplateIntentFactoryEnabled())
+ .println();
+ pw.printPair("translate_in_classification_enabled", isTranslateInClassificationEnabled())
+ .println();
pw.decreaseIndent();
- pw.println();
}
-}
+}
\ No newline at end of file
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index 042b943..95ca9de 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -45,6 +45,9 @@
private static final String LOG_TAG = "TextClassificationManager";
+ private static final TextClassificationConstants sDefaultSettings =
+ new TextClassificationConstants(() -> null);
+
private final Object mLock = new Object();
private final TextClassificationSessionFactory mDefaultSessionFactory =
classificationContext -> new TextClassificationSession(
@@ -129,9 +132,10 @@
private TextClassificationConstants getSettings() {
synchronized (mLock) {
if (mSettings == null) {
- mSettings = TextClassificationConstants.loadFromString(Settings.Global.getString(
- getApplicationContext().getContentResolver(),
- Settings.Global.TEXT_CLASSIFIER_CONSTANTS));
+ mSettings = new TextClassificationConstants(
+ () -> Settings.Global.getString(
+ getApplicationContext().getContentResolver(),
+ Settings.Global.TEXT_CLASSIFIER_CONSTANTS));
}
return mSettings;
}
@@ -251,7 +255,11 @@
/** @hide */
@VisibleForTesting
- public void invalidate() {
+ public void invalidateForTesting() {
+ invalidate();
+ }
+
+ private void invalidate() {
synchronized (mLock) {
mSettings = null;
mLocalTextClassifier = null;
@@ -280,9 +288,8 @@
if (tcm != null) {
return tcm.getSettings();
} else {
- return TextClassificationConstants.loadFromString(Settings.Global.getString(
- context.getApplicationContext().getContentResolver(),
- Settings.Global.TEXT_CLASSIFIER_CONSTANTS));
+ // Use default settings if there is no tcm.
+ return sDefaultSettings;
}
}
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 3297523..3e95f1b 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -301,7 +301,7 @@
final ZonedDateTime refTime = ZonedDateTime.now();
final Collection<String> entitiesToIdentify = request.getEntityConfig() != null
? request.getEntityConfig().resolveEntityListModifications(
- getEntitiesForHints(request.getEntityConfig().getHints()))
+ getEntitiesForHints(request.getEntityConfig().getHints()))
: mSettings.getEntityListDefault();
final String localesString = concatenateLocales(request.getDefaultLocales());
final String detectLanguageTags = detectLanguageTagsFromText(request.getText());
@@ -779,8 +779,8 @@
final float moreTextScoreRatio = 1f - subjectTextScoreRatio;
Log.v(LOG_TAG,
String.format(Locale.US, "LangIdContextSettings: "
- + "minimumTextSize=%d, penalizeRatio=%.2f, "
- + "subjectTextScoreRatio=%.2f, moreTextScoreRatio=%.2f",
+ + "minimumTextSize=%d, penalizeRatio=%.2f, "
+ + "subjectTextScoreRatio=%.2f, moreTextScoreRatio=%.2f",
minimumTextSize, penalizeRatio, subjectTextScoreRatio, moreTextScoreRatio));
if (end - start < minimumTextSize && penalizeRatio <= 0) {
@@ -903,4 +903,3 @@
}
}
}
-
diff --git a/core/java/android/webkit/WebViewLibraryLoader.java b/core/java/android/webkit/WebViewLibraryLoader.java
index 5a6aeba..be49fc4 100644
--- a/core/java/android/webkit/WebViewLibraryLoader.java
+++ b/core/java/android/webkit/WebViewLibraryLoader.java
@@ -181,9 +181,9 @@
boolean is64Bit = VMRuntime.getRuntime().is64Bit();
// On 64-bit address space is really cheap and we can reserve 1GB which is plenty.
// On 32-bit it's fairly scarce and we should keep it to a realistic number that
- // permits some future growth but doesn't hog space: we use 100MB which is more than 2x
- // the current requirement.
- long addressSpaceToReserve = is64Bit ? 1 * 1024 * 1024 * 1024 : 100 * 1024 * 1024;
+ // permits some future growth but doesn't hog space: we use 130MB which is roughly
+ // what was calculated on older OS versions in practice.
+ long addressSpaceToReserve = is64Bit ? 1 * 1024 * 1024 * 1024 : 130 * 1024 * 1024;
sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve);
if (sAddressSpaceReserved) {
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 4c32f03..d985528 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1992,7 +1992,7 @@
// dependencies for a specific set of rules
for (int j = 0; j < rulesCount; j++) {
final int rule = rules[rulesFilter[j]];
- if (ResourceId.isValid(rule)) {
+ if (rule > 0 || ResourceId.isValid(rule)) {
// The node this node depends on
final Node dependency = keyNodes.get(rule);
// Skip unknowns and self dependencies
diff --git a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
index fb27a2f..3fddfc8 100644
--- a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
+++ b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
@@ -26,7 +26,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
-import android.os.Handler;
import android.os.Message;
import android.os.UserHandle;
import android.util.Log;
@@ -37,6 +36,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executors;
/**
* Uses an {@link AppPredictor} to sort Resolver targets. If the AppPredictionService appears to be
@@ -46,7 +46,7 @@
class AppPredictionServiceResolverComparator extends AbstractResolverComparator {
private static final String TAG = "APSResolverComparator";
- private static final long DELAY_COMPUTE_WHEN_DEFAULTING_TO_RESOLVER_MILLIS = 200;
+ private static final boolean DEBUG = false;
private final AppPredictor mAppPredictor;
private final Context mContext;
@@ -103,23 +103,22 @@
.setTarget(target.name.getPackageName(), mUser)
.setClassName(target.name.getClassName()).build());
}
- mAppPredictor.sortTargets(appTargets, mContext.getMainExecutor(),
+ mAppPredictor.sortTargets(appTargets, Executors.newSingleThreadExecutor(),
sortedAppTargets -> {
if (sortedAppTargets.isEmpty()) {
+ if (DEBUG) {
+ Log.d(TAG, "AppPredictionService disabled. Using resolver.");
+ }
// APS for chooser is disabled. Fallback to resolver.
mResolverRankerService =
new ResolverRankerServiceResolverComparator(
mContext, mIntent, mReferrerPackage,
() -> mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT));
- mResolverRankerService.initRanker(mContext);
- Handler computeHandler =
- new Handler(msg -> {
- mResolverRankerService.compute(targets);
- return true;
- });
- computeHandler.sendEmptyMessageDelayed(
- 0, DELAY_COMPUTE_WHEN_DEFAULTING_TO_RESOLVER_MILLIS);
+ mResolverRankerService.compute(targets);
} else {
+ if (DEBUG) {
+ Log.d(TAG, "AppPredictionService response received");
+ }
Message msg =
Message.obtain(mHandler, RANKER_SERVICE_RESULT, sortedAppTargets);
msg.sendToTarget();
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 96331c2..5924fb15 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -153,8 +153,8 @@
* {@link AppPredictionManager} will be queried for direct share targets.
*/
// TODO(b/123089490): Replace with system flag
- private static final boolean USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS = false;
- private static final boolean USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES = false;
+ private static final boolean USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS = true;
+ private static final boolean USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES = true;
// TODO(b/123088566) Share these in a better way.
private static final String APP_PREDICTION_SHARE_UI_SURFACE = "share";
public static final String LAUNCH_LOCATON_DIRECT_SHARE = "direct_share";
@@ -177,7 +177,7 @@
*/
private static final int NO_DIRECT_SHARE_ANIM_IN_MILLIS = 200;
- private static final float DIRECT_SHARE_EXPANSION_RATE = 0.7f;
+ private static final float DIRECT_SHARE_EXPANSION_RATE = 0.78f;
// TODO(b/121287224): Re-evaluate this limit
private static final int SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20;
@@ -202,6 +202,9 @@
private long mChooserShownTime;
protected boolean mIsSuccessfullySelected;
+ private long mQueriedTargetServicesTimeMs;
+ private long mQueriedSharingShortcutsTimeMs;
+
private ChooserListAdapter mChooserListAdapter;
private ChooserRowAdapter mChooserRowAdapter;
private int mChooserRowServiceSpacing;
@@ -209,7 +212,7 @@
/** {@link ChooserActivity#getBaseScore} */
private static final float CALLER_TARGET_SCORE_BOOST = 900.f;
/** {@link ChooserActivity#getBaseScore} */
- private static final float SHORTCUT_TARGET_SCORE_BOOST = 10.f;
+ private static final float SHORTCUT_TARGET_SCORE_BOOST = 90.f;
private static final String TARGET_DETAILS_FRAGMENT_TAG = "targetDetailsFragment";
// TODO: Update to handle landscape instead of using static value
private static final int MAX_RANKED_TARGETS = 4;
@@ -273,6 +276,8 @@
sri.connection.destroy();
mServiceConnections.remove(sri.connection);
if (mServiceConnections.isEmpty()) {
+ logDirectShareTargetReceived(
+ MetricsEvent.ACTION_DIRECT_SHARE_TARGETS_LOADED_CHOOSER_SERVICE);
sendVoiceChoicesIfNeeded();
}
break;
@@ -283,6 +288,8 @@
}
unbindRemainingServices();
+ logDirectShareTargetReceived(
+ MetricsEvent.ACTION_DIRECT_SHARE_TARGETS_LOADED_CHOOSER_SERVICE);
sendVoiceChoicesIfNeeded();
mChooserListAdapter.completeServiceTargetLoading();
break;
@@ -305,6 +312,8 @@
break;
case SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED:
+ logDirectShareTargetReceived(
+ MetricsEvent.ACTION_DIRECT_SHARE_TARGETS_LOADED_SHORTCUT_MANAGER);
sendVoiceChoicesIfNeeded();
break;
@@ -770,7 +779,7 @@
}
}
} catch (SecurityException | NullPointerException e) {
- Log.w(TAG, "Error loading file preview", e);
+ logContentPreviewWarning(uri);
}
if (TextUtils.isEmpty(fileName)) {
@@ -784,6 +793,14 @@
return new FileInfo(fileName, hasThumbnail);
}
+ private void logContentPreviewWarning(Uri uri) {
+ // The ContentResolver already logs the exception. Log something more informative.
+ Log.w(TAG, "Could not load (" + uri.toString() + ") thumbnail/name for preview. If "
+ + "desired, consider using Intent#createChooser to launch the ChooserActivity, "
+ + "and set your Intent's clipData and flags in accordance with that method's "
+ + "documentation");
+ }
+
private ViewGroup displayFileContentPreview(Intent targetIntent, LayoutInflater layoutInflater,
ViewGroup convertView, ViewGroup parent) {
@@ -1155,6 +1172,8 @@
}
void queryTargetServices(ChooserListAdapter adapter) {
+ mQueriedTargetServicesTimeMs = System.currentTimeMillis();
+
final PackageManager pm = getPackageManager();
ShortcutManager sm = (ShortcutManager) getSystemService(ShortcutManager.class);
int targetsToQuery = 0;
@@ -1281,6 +1300,7 @@
private void queryDirectShareTargets(
ChooserListAdapter adapter, boolean skipAppPredictionService) {
+ mQueriedSharingShortcutsTimeMs = System.currentTimeMillis();
if (!skipAppPredictionService) {
AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
if (appPredictor != null) {
@@ -1391,6 +1411,14 @@
// Do nothing. We'll send the voice stuff ourselves.
}
+ private void logDirectShareTargetReceived(int logCategory) {
+ final long queryTime =
+ logCategory == MetricsEvent.ACTION_DIRECT_SHARE_TARGETS_LOADED_SHORTCUT_MANAGER
+ ? mQueriedSharingShortcutsTimeMs : mQueriedTargetServicesTimeMs;
+ final int apiLatency = (int) (System.currentTimeMillis() - queryTime);
+ getMetricsLogger().write(new LogMaker(logCategory).setSubtype(apiLatency));
+ }
+
void updateModelAndChooserCounts(TargetInfo info) {
if (info != null) {
sendClickToAppPredictor(info);
@@ -1644,7 +1672,7 @@
try {
return ImageUtils.loadThumbnail(getContentResolver(), uri, size);
} catch (IOException | NullPointerException | SecurityException ex) {
- Log.w(TAG, "Error loading preview thumbnail for uri: " + uri.toString(), ex);
+ logContentPreviewWarning(uri);
}
return null;
}
@@ -2037,21 +2065,29 @@
return;
}
- int lastHeight = 0;
+ int directShareHeight = 0;
rowsToShow = Math.min(4, rowsToShow);
for (int i = 0; i < Math.min(rowsToShow, mAdapterView.getChildCount()); i++) {
- lastHeight = mAdapterView.getChildAt(i).getHeight();
- offset += lastHeight;
+ View child = mAdapterView.getChildAt(i);
+ int height = child.getHeight();
+ offset += height;
+
+ if (child.getTag() != null
+ && (child.getTag() instanceof DirectShareViewHolder)) {
+ directShareHeight = height;
+ }
}
boolean isPortrait = getResources().getConfiguration().orientation
== Configuration.ORIENTATION_PORTRAIT;
- if (lastHeight != 0 && isSendAction(getTargetIntent()) && isPortrait) {
+ if (directShareHeight != 0 && isSendAction(getTargetIntent()) && isPortrait) {
// make sure to leave room for direct share 4->8 expansion
- int expansionArea =
- (int) (mResolverDrawerLayout.getAlwaysShowHeight()
- / DIRECT_SHARE_EXPANSION_RATE);
- offset = Math.min(offset, bottom - top - lastHeight - expansionArea);
+ int requiredExpansionHeight =
+ (int) (directShareHeight / DIRECT_SHARE_EXPANSION_RATE);
+ int minHeight = bottom - top - mResolverDrawerLayout.getAlwaysShowHeight()
+ - requiredExpansionHeight;
+
+ offset = Math.min(offset, minHeight);
}
mResolverDrawerLayout.setCollapsibleHeightReserved(Math.min(offset, bottom - top));
@@ -2072,6 +2108,8 @@
private static final int MAX_SERVICE_TARGETS = 8;
+ private int mNumShortcutResults = 0;
+
// Reserve spots for incoming direct share targets by adding placeholders
private ChooserTargetInfo mPlaceHolderTargetInfo = new PlaceHolderTargetInfo();
private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
@@ -2178,7 +2216,7 @@
protected void onBindView(View view, TargetInfo info) {
super.onBindView(view, info);
- // If target is loading, show a special placeholder shape in the label
+ // If target is loading, show a special placeholder shape in the label, make unclickable
final ViewHolder holder = (ViewHolder) view.getTag();
if (info instanceof PlaceHolderTargetInfo) {
final int maxWidth = getResources().getDimensionPixelSize(
@@ -2186,9 +2224,12 @@
holder.text.setMaxWidth(maxWidth);
holder.text.setBackground(getResources().getDrawable(
R.drawable.chooser_direct_share_label_placeholder, getTheme()));
+ // Prevent rippling by removing background containing ripple
+ holder.itemView.setBackground(null);
} else {
holder.text.setMaxWidth(Integer.MAX_VALUE);
holder.text.setBackground(null);
+ holder.itemView.setBackground(holder.defaultItemViewBackground);
}
}
@@ -2407,9 +2448,15 @@
// This incents ChooserTargetServices to define what's truly better.
targetScore = lastScore * 0.95f;
}
- shouldNotify |= insertServiceTarget(
+ boolean isInserted = insertServiceTarget(
new SelectableTargetInfo(origTarget, target, targetScore));
+ if (isInserted && isShortcutResult) {
+ mNumShortcutResults++;
+ }
+
+ shouldNotify |= isInserted;
+
if (DEBUG) {
Log.d(TAG, " => " + target.toString() + " score=" + targetScore
+ " base=" + target.getScore()
@@ -2425,11 +2472,16 @@
}
}
+ private int getNumShortcutResults() {
+ return mNumShortcutResults;
+ }
+
/**
- * Use the scoring system along with artificial boosts to create up to 3 distinct buckets:
+ * Use the scoring system along with artificial boosts to create up to 4 distinct buckets:
* <ol>
* <li>App-supplied targets
- * <li>Prediction manager targets or Shortcut API targets
+ * <li>Shortcuts ranked via App Prediction Manager
+ * <li>Shortcuts ranked via legacy heuristics
* <li>Legacy direct share targets
* </ol>
*/
@@ -2438,7 +2490,7 @@
return CALLER_TARGET_SCORE_BOOST;
}
- if (getAppPredictorForDirectShareIfEnabled() != null) {
+ if (isShortcutResult && getAppPredictorForDirectShareIfEnabled() != null) {
return SHORTCUT_TARGET_SCORE_BOOST;
}
@@ -2881,10 +2933,10 @@
if (startType != lastStartType
|| rowPosition == getContentPreviewRowCount() + getProfileRowCount()) {
- row.setBackground(
+ row.setForeground(
getResources().getDrawable(R.drawable.chooser_row_layer_list, null));
} else {
- row.setBackground(null);
+ row.setForeground(null);
}
int columnCount = holder.getColumnCount();
@@ -2955,7 +3007,15 @@
}
public void handleScroll(View v, int y, int oldy) {
- if (mDirectShareViewHolder != null) {
+ // Only expand direct share area if there is a minimum number of shortcuts,
+ // which will help reduce the amount of visible shuffling due to older-style
+ // direct share targets.
+ int orientation = getResources().getConfiguration().orientation;
+ boolean canExpandDirectShare =
+ mChooserListAdapter.getNumShortcutResults() > getMaxTargetsPerRow()
+ && orientation == Configuration.ORIENTATION_PORTRAIT;
+
+ if (mDirectShareViewHolder != null && canExpandDirectShare) {
mDirectShareViewHolder.handleScroll(mAdapterView, y, oldy, getMaxTargetsPerRow());
}
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 5e4918d..3ea746d 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -2061,11 +2061,16 @@
}
static class ViewHolder {
+ public View itemView;
+ public Drawable defaultItemViewBackground;
+
public TextView text;
public TextView text2;
public ImageView icon;
public ViewHolder(View view) {
+ itemView = view;
+ defaultItemViewBackground = view.getBackground();
text = (TextView) view.findViewById(com.android.internal.R.id.text1);
text2 = (TextView) view.findViewById(com.android.internal.R.id.text2);
icon = (ImageView) view.findViewById(R.id.icon);
diff --git a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
index d633467..01e0622 100644
--- a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
@@ -315,7 +315,7 @@
}
// connect to a ranking service.
- void initRanker(Context context) {
+ private void initRanker(Context context) {
synchronized (mLock) {
if (mConnection != null && mRanker != null) {
if (DEBUG) {
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index 9e8bd64..cdb79ab 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -60,9 +60,11 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
* A helper class for {@link android.provider.DocumentsProvider} to perform file operations on local
@@ -245,7 +247,6 @@
}
childId = getDocIdForFile(file);
onDocIdChanged(childId);
- addFolderToMediaStore(getFileForDocId(childId, true));
} else {
try {
if (!file.createNewFile()) {
@@ -257,19 +258,11 @@
throw new IllegalStateException("Failed to touch " + file + ": " + e);
}
}
+ MediaStore.scanFile(getContext(), file);
return childId;
}
- private void addFolderToMediaStore(@Nullable File visibleFolder) {
- // visibleFolder is null if we're adding a folder to external thumb drive or SD card.
- if (visibleFolder != null) {
- assert (visibleFolder.isDirectory());
-
- MediaStore.scanFile(getContext(), visibleFolder);
- }
- }
-
@Override
public String renameDocument(String docId, String displayName) throws FileNotFoundException {
// Since this provider treats renames as generating a completely new
@@ -291,7 +284,6 @@
moveInMediaStore(beforeVisibleFile, afterVisibleFile);
if (!TextUtils.equals(docId, afterDocId)) {
- scanFile(afterVisibleFile);
return afterDocId;
} else {
return null;
@@ -613,28 +605,28 @@
return projection == null ? mDefaultProjection : projection;
}
- private void startObserving(File file, Uri notifyUri) {
+ private void startObserving(File file, Uri notifyUri, DirectoryCursor cursor) {
synchronized (mObservers) {
DirectoryObserver observer = mObservers.get(file);
if (observer == null) {
- observer = new DirectoryObserver(
- file, getContext().getContentResolver(), notifyUri);
+ observer =
+ new DirectoryObserver(file, getContext().getContentResolver(), notifyUri);
observer.startWatching();
mObservers.put(file, observer);
}
- observer.mRefCount++;
+ observer.mCursors.add(cursor);
if (LOG_INOTIFY) Log.d(TAG, "after start: " + observer);
}
}
- private void stopObserving(File file) {
+ private void stopObserving(File file, DirectoryCursor cursor) {
synchronized (mObservers) {
DirectoryObserver observer = mObservers.get(file);
if (observer == null) return;
- observer.mRefCount--;
- if (observer.mRefCount == 0) {
+ observer.mCursors.remove(cursor);
+ if (observer.mCursors.size() == 0) {
mObservers.remove(file);
observer.stopWatching();
}
@@ -650,27 +642,31 @@
private final File mFile;
private final ContentResolver mResolver;
private final Uri mNotifyUri;
+ private final CopyOnWriteArrayList<DirectoryCursor> mCursors;
- private int mRefCount = 0;
-
- public DirectoryObserver(File file, ContentResolver resolver, Uri notifyUri) {
+ DirectoryObserver(File file, ContentResolver resolver, Uri notifyUri) {
super(file.getAbsolutePath(), NOTIFY_EVENTS);
mFile = file;
mResolver = resolver;
mNotifyUri = notifyUri;
+ mCursors = new CopyOnWriteArrayList<>();
}
@Override
public void onEvent(int event, String path) {
if ((event & NOTIFY_EVENTS) != 0) {
if (LOG_INOTIFY) Log.d(TAG, "onEvent() " + event + " at " + path);
+ for (DirectoryCursor cursor : mCursors) {
+ cursor.notifyChanged();
+ }
mResolver.notifyChange(mNotifyUri, null, false);
}
}
@Override
public String toString() {
- return "DirectoryObserver{file=" + mFile.getAbsolutePath() + ", ref=" + mRefCount + "}";
+ String filePath = mFile.getAbsolutePath();
+ return "DirectoryObserver{file=" + filePath + ", ref=" + mCursors.size() + "}";
}
}
@@ -681,16 +677,22 @@
super(columnNames);
final Uri notifyUri = buildNotificationUri(docId);
- setNotificationUri(getContext().getContentResolver(), notifyUri);
+ boolean registerSelfObserver = false; // Our FileObserver sees all relevant changes.
+ setNotificationUris(getContext().getContentResolver(), Arrays.asList(notifyUri),
+ getContext().getContentResolver().getUserId(), registerSelfObserver);
mFile = file;
- startObserving(mFile, notifyUri);
+ startObserving(mFile, notifyUri, this);
+ }
+
+ public void notifyChanged() {
+ onChange(false);
}
@Override
public void close() {
super.close();
- stopObserving(mFile);
+ stopObserving(mFile, this);
}
}
}
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index 5d08a25..ad1ff90 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -64,6 +64,8 @@
public static final int RECOMMEND_MEDIA_UNAVAILABLE = -5;
public static final int RECOMMEND_FAILED_INVALID_URI = -6;
public static final int RECOMMEND_FAILED_VERSION_DOWNGRADE = -7;
+ /** {@hide} */
+ public static final int RECOMMEND_FAILED_WRONG_INSTALLED_VERSION = -8;
private static final String TAG = "PackageHelper";
// App installation location settings values
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index 64f8857..3900f16 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -231,6 +231,7 @@
@SuppressWarnings("unchecked") // TODO(b/117779333): fix this warning
final S castService = (S) this;
mVultureCallback.onServiceDied(castService);
+ handleBindFailure();
}
// Note: we are dumping without a lock held so this is a bit racy but
@@ -406,7 +407,8 @@
@NonNull BasePendingRequest<S, I> pendingRequest);
/**
- * Called if {@link Context#bindServiceAsUser} returns {@code false}.
+ * Called if {@link Context#bindServiceAsUser} returns {@code false}, or
+ * if {@link DeathRecipient#binderDied()} is called.
*/
abstract void handleBindFailure();
@@ -431,8 +433,6 @@
mBinding = false;
if (!mServiceDied) {
- // TODO(b/126266412): merge these 2 calls?
- handleBindFailure();
handleBinderDied();
}
}
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index accfc87..a35e42e 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -43,7 +43,12 @@
public static String NETWORK_ALERTS = "NETWORK_ALERTS";
public static String NETWORK_AVAILABLE = "NETWORK_AVAILABLE";
public static String VPN = "VPN";
- public static String DEVICE_ADMIN = "DEVICE_ADMIN";
+ /**
+ * @deprecated Legacy device admin channel with low importance which is no longer used,
+ * Use the high importance {@link #DEVICE_ADMIN} channel instead.
+ */
+ @Deprecated public static String DEVICE_ADMIN_DEPRECATED = "DEVICE_ADMIN";
+ public static String DEVICE_ADMIN = "DEVICE_ADMIN_ALERTS";
public static String ALERTS = "ALERTS";
public static String RETAIL_MODE = "RETAIL_MODE";
public static String USB = "USB";
@@ -128,7 +133,7 @@
final NotificationChannel deviceAdmin = new NotificationChannel(
DEVICE_ADMIN,
context.getString(R.string.notification_channel_device_admin),
- NotificationManager.IMPORTANCE_LOW);
+ NotificationManager.IMPORTANCE_HIGH);
channelsList.add(deviceAdmin);
final NotificationChannel alertsChannel = new NotificationChannel(
@@ -180,6 +185,12 @@
nm.createNotificationChannels(channelsList);
}
+ /** Remove notification channels which are no longer used */
+ public static void removeDeprecated(Context context) {
+ final NotificationManager nm = context.getSystemService(NotificationManager.class);
+ nm.deleteNotificationChannel(DEVICE_ADMIN_DEPRECATED);
+ }
+
public static void createAccountChannelForPackage(String pkg, int uid, Context context) {
final INotificationManager iNotificationManager = NotificationManager.getService();
try {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 72f6c12..c04a249 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -12028,7 +12028,7 @@
// if the device is now charging, it means that this is either called
// 1. directly when level >= 90
// 2. or from within the runnable that we deferred
- // For 1. if we have an existing callback, remove it, since we will immediatelly send a
+ // For 1. if we have an existing callback, remove it, since we will immediately send a
// ACTION_CHARGING
// For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
mHandler.removeCallbacks(mDeferSetCharging);
@@ -12369,7 +12369,6 @@
// If the battery level is at least 90%, always consider the device to be
// charging even if it happens to go down a level.
changed |= setChargingLocked(true);
- mLastChargeStepLevel = level;
} else if (!mCharging) {
if (mLastChargeStepLevel < level) {
// We have not reported that we are charging, but the level has gone up,
@@ -12395,17 +12394,16 @@
changed |= setChargingLocked(false);
}
}
- mLastChargeStepLevel = level;
if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
modeBits, elapsedRealtime);
mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
modeBits, elapsedRealtime);
- mLastChargeStepLevel = level;
mMaxChargeStepLevel = level;
mInitStepMode = mCurStepMode;
mModStepMode = 0;
}
+ mLastChargeStepLevel = level;
}
if (changed) {
addHistoryRecordLocked(elapsedRealtime, uptime);
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 99175b8..2736c6a 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -234,14 +234,13 @@
public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
- String packageName, String[] packagesForUID, String sandboxId, int targetSdkVersion) {
+ int targetSdkVersion) {
ZygoteHooks.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
- fdsToIgnore, startChildZygote, instructionSet, appDataDir, packageName,
- packagesForUID, sandboxId);
+ fdsToIgnore, startChildZygote, instructionSet, appDataDir);
// Enable tracing as soon as possible for the child process.
if (pid == 0) {
Zygote.disableExecuteOnly(targetSdkVersion);
@@ -257,8 +256,7 @@
private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
- String appDataDir, String packageName, String[] packagesForUID,
- String sandboxId);
+ String appDataDir);
/**
* Specialize an unspecialized app process. The current VM must have been started
@@ -283,11 +281,9 @@
*/
public static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName,
- boolean startChildZygote, String instructionSet, String appDataDir, String packageName,
- String[] packagesForUID, String sandboxId) {
+ boolean startChildZygote, String instructionSet, String appDataDir) {
nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
- niceName, startChildZygote, instructionSet, appDataDir,
- packageName, packagesForUID, sandboxId);
+ niceName, startChildZygote, instructionSet, appDataDir);
// Enable tracing as soon as possible for the child process.
Trace.setTracingEnabled(true, runtimeFlags);
@@ -306,8 +302,7 @@
private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids,
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
- boolean startChildZygote, String instructionSet, String appDataDir, String packageName,
- String[] packagesForUID, String sandboxId);
+ boolean startChildZygote, String instructionSet, String appDataDir);
/**
* Called to do any initialization before starting an application.
@@ -607,8 +602,7 @@
specializeAppProcess(args.mUid, args.mGid, args.mGids,
args.mRuntimeFlags, rlimits, args.mMountExternal,
args.mSeInfo, args.mNiceName, args.mStartChildZygote,
- args.mInstructionSet, args.mAppDataDir, args.mPackageName,
- args.mPackagesForUid, args.mSandboxId);
+ args.mInstructionSet, args.mAppDataDir);
disableExecuteOnly(args.mTargetSdkVersion);
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index 28642d8..2564f6b 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -119,12 +119,6 @@
/** from --package-name */
String mPackageName;
- /** from --packages-for-uid */
- String[] mPackagesForUid;
-
- /** from --sandbox-id */
- String mSandboxId;
-
/**
* Any args after and including the first non-option arg (or after a '--')
*/
@@ -411,13 +405,6 @@
throw new IllegalArgumentException("Duplicate arg specified");
}
mPackageName = arg.substring(arg.indexOf('=') + 1);
- } else if (arg.startsWith("--packages-for-uid=")) {
- mPackagesForUid = arg.substring(arg.indexOf('=') + 1).split(",");
- } else if (arg.startsWith("--sandbox-id=")) {
- if (mSandboxId != null) {
- throw new IllegalArgumentException("Duplicate arg specified");
- }
- mSandboxId = arg.substring(arg.indexOf('=') + 1);
} else if (arg.startsWith("--usap-pool-enabled=")) {
mUsapPoolStatusSpecified = true;
mUsapPoolEnabled = Boolean.parseBoolean(arg.substring(arg.indexOf('=') + 1));
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index dd6fb72..785256e 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -267,8 +267,7 @@
pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
- parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mPackageName,
- parsedArgs.mPackagesForUid, parsedArgs.mSandboxId, parsedArgs.mTargetSdkVersion);
+ parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
try {
if (pid == 0) {
@@ -406,8 +405,13 @@
private int mHiddenApiAccessStatslogSampleRate = 0;
public static void setHiddenApiAccessLogSampleRates(int sampleRate, int newSampleRate) {
- sInstance.mHiddenApiAccessLogSampleRate = sampleRate;
- sInstance.mHiddenApiAccessStatslogSampleRate = newSampleRate;
+ if (sampleRate != -1) {
+ sInstance.mHiddenApiAccessLogSampleRate = sampleRate;
+ }
+
+ if (newSampleRate != -1) {
+ sInstance.mHiddenApiAccessStatslogSampleRate = newSampleRate;
+ }
}
public static HiddenApiUsageLogger getInstance() {
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index d50a70e..9a10210 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -630,7 +630,8 @@
drawingBounds.bottom -= framePadding.bottom - frameOffsets.bottom;
}
- Drawable bg = getBackground();
+ // Need to call super here as we pretend to be having the original background.
+ Drawable bg = super.getBackground();
if (bg != null) {
bg.setBounds(drawingBounds);
}
@@ -975,6 +976,18 @@
}
}
+ @Override
+ public void setBackgroundDrawable(Drawable background) {
+
+ // TODO: This should route through setWindowBackground, but late in the release to make this
+ // change.
+ if (mOriginalBackgroundDrawable != background) {
+ mOriginalBackgroundDrawable = background;
+ updateBackgroundDrawable();
+ drawableChanged();
+ }
+ }
+
public void setWindowFrame(Drawable drawable) {
if (getForeground() != drawable) {
setForeground(drawable);
@@ -1161,12 +1174,16 @@
// If we didn't request fullscreen layout, but we still got it because of the
// mForceWindowDrawsBarBackgrounds flag, also consume top inset.
+ // If we should always consume system bars, only consume that if the app wanted to go to
+ // fullscreen, as othrewise we can expect the app to handle it.
+ boolean fullscreen = (sysUiVisibility & SYSTEM_UI_FLAG_FULLSCREEN) != 0
+ || (attrs.flags & FLAG_FULLSCREEN) != 0;
boolean consumingStatusBar = (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0
&& (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0
&& (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0
&& mForceWindowDrawsBarBackgrounds
&& mLastTopInset != 0
- || mLastShouldAlwaysConsumeSystemBars;
+ || (mLastShouldAlwaysConsumeSystemBars && fullscreen);
int consumedTop = consumingStatusBar ? mLastTopInset : 0;
int consumedRight = consumingNavBar ? mLastRightInset : 0;
@@ -1213,14 +1230,22 @@
* are set.
*/
private void updateBackgroundDrawable() {
+ // Background insets can be null if super constructor calls setBackgroundDrawable.
+ if (mBackgroundInsets == null) {
+ mBackgroundInsets = Insets.NONE;
+ }
if (mBackgroundInsets.equals(mLastBackgroundInsets)
&& mLastOriginalBackgroundDrawable == mOriginalBackgroundDrawable) {
return;
}
if (mOriginalBackgroundDrawable == null || mBackgroundInsets.equals(Insets.NONE)) {
- setBackground(mOriginalBackgroundDrawable);
+
+ // Call super since we are intercepting setBackground on this class.
+ super.setBackgroundDrawable(mOriginalBackgroundDrawable);
} else {
- setBackground(new InsetDrawable(mOriginalBackgroundDrawable,
+
+ // Call super since we are intercepting setBackground on this class.
+ super.setBackgroundDrawable(new InsetDrawable(mOriginalBackgroundDrawable,
mBackgroundInsets.left, mBackgroundInsets.top,
mBackgroundInsets.right, mBackgroundInsets.bottom) {
@@ -1238,6 +1263,11 @@
mLastOriginalBackgroundDrawable = mOriginalBackgroundDrawable;
}
+ @Override
+ public Drawable getBackground() {
+ return mOriginalBackgroundDrawable;
+ }
+
private int calculateStatusBarColor() {
return calculateBarColor(mWindow.getAttributes().flags, FLAG_TRANSLUCENT_STATUS,
mSemiTransparentBarColor, mWindow.mStatusBarColor,
@@ -1527,10 +1557,14 @@
return;
}
- setPadding(mFramePadding.left + mBackgroundPadding.left,
- mFramePadding.top + mBackgroundPadding.top,
- mFramePadding.right + mBackgroundPadding.right,
- mFramePadding.bottom + mBackgroundPadding.bottom);
+ // Fields can be null if super constructor calls setBackgroundDrawable.
+ Rect framePadding = mFramePadding != null ? mFramePadding : new Rect();
+ Rect backgroundPadding = mBackgroundPadding != null ? mBackgroundPadding : new Rect();
+
+ setPadding(framePadding.left + backgroundPadding.left,
+ framePadding.top + backgroundPadding.top,
+ framePadding.right + backgroundPadding.right,
+ framePadding.bottom + backgroundPadding.bottom);
requestLayout();
invalidate();
@@ -1550,8 +1584,8 @@
if (bg != null) {
if (fg == null) {
opacity = bg.getOpacity();
- } else if (mFramePadding.left <= 0 && mFramePadding.top <= 0
- && mFramePadding.right <= 0 && mFramePadding.bottom <= 0) {
+ } else if (framePadding.left <= 0 && framePadding.top <= 0
+ && framePadding.right <= 0 && framePadding.bottom <= 0) {
// If the frame padding is zero, then we can be opaque
// if either the frame -or- the background is opaque.
int fop = fg.getOpacity();
@@ -1958,8 +1992,7 @@
final boolean isFullscreen = config.windowConfiguration.getWindowingMode()
== WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
return isFullscreen && (0 != ((getWindowSystemUiVisibility() | getSystemUiVisibility())
- & (View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_LOW_PROFILE)));
+ & View.SYSTEM_UI_FLAG_FULLSCREEN));
}
private void updateDecorCaptionStatus(Configuration config) {
diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl
index 2cfdaaa..41f902e 100644
--- a/core/java/com/android/internal/view/IInputMethodClient.aidl
+++ b/core/java/com/android/internal/view/IInputMethodClient.aidl
@@ -31,4 +31,5 @@
void reportFullscreenMode(boolean fullscreen);
void reportPreRendered(in EditorInfo info);
void applyImeVisibility(boolean setVisible);
+ void updateActivityViewToScreenMatrix(int bindSequence, in float[] matrixValues);
}
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index cb18ca1..c29e823 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -68,4 +68,7 @@
// This is kept due to @UnsupportedAppUsage.
// TODO(Bug 113914148): Consider removing this.
int getInputMethodWindowVisibleHeight();
+
+ void reportActivityView(in IInputMethodClient parentClient, int childDisplayId,
+ in float[] matrixValues);
}
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index 9fe49b4..1b133d2 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -19,10 +19,12 @@
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.graphics.Matrix;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -192,13 +194,37 @@
*/
public final int sequence;
+ @Nullable
+ private final float[] mActivityViewToScreenMatrixValues;
+
+ /**
+ * @return {@link Matrix} that corresponds to {@link #mActivityViewToScreenMatrixValues}.
+ * {@code null} if {@link #mActivityViewToScreenMatrixValues} is {@code null}.
+ */
+ @Nullable
+ public Matrix getActivityViewToScreenMatrix() {
+ if (mActivityViewToScreenMatrixValues == null) {
+ return null;
+ }
+ final Matrix matrix = new Matrix();
+ matrix.setValues(mActivityViewToScreenMatrixValues);
+ return matrix;
+ }
+
public InputBindResult(@ResultCode int _result,
- IInputMethodSession _method, InputChannel _channel, String _id, int _sequence) {
+ IInputMethodSession _method, InputChannel _channel, String _id, int _sequence,
+ @Nullable Matrix activityViewToScreenMatrix) {
result = _result;
method = _method;
channel = _channel;
id = _id;
sequence = _sequence;
+ if (activityViewToScreenMatrix == null) {
+ mActivityViewToScreenMatrixValues = null;
+ } else {
+ mActivityViewToScreenMatrixValues = new float[9];
+ activityViewToScreenMatrix.getValues(mActivityViewToScreenMatrixValues);
+ }
}
InputBindResult(Parcel source) {
@@ -211,12 +237,14 @@
}
id = source.readString();
sequence = source.readInt();
+ mActivityViewToScreenMatrixValues = source.createFloatArray();
}
@Override
public String toString() {
return "InputBindResult{result=" + getResultString() + " method="+ method + " id=" + id
+ " sequence=" + sequence
+ + " activityViewToScreenMatrix=" + getActivityViewToScreenMatrix()
+ "}";
}
@@ -238,6 +266,7 @@
}
dest.writeString(id);
dest.writeInt(sequence);
+ dest.writeFloatArray(mActivityViewToScreenMatrixValues);
}
/**
@@ -302,7 +331,7 @@
}
private static InputBindResult error(@ResultCode int result) {
- return new InputBindResult(result, null, null, null, -1);
+ return new InputBindResult(result, null, null, null, -1, null);
}
/**
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 3881093..9084f62 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -26,6 +26,7 @@
import android.graphics.Region;
import android.hardware.input.InputManager;
import android.hardware.input.InputManager.InputDeviceListener;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.util.Log;
@@ -745,11 +746,16 @@
super.onAttachedToWindow();
mIm.registerInputDeviceListener(this, getHandler());
- try {
- WindowManagerGlobal.getWindowManagerService().registerSystemGestureExclusionListener(
- mSystemGestureExclusionListener, mContext.getDisplayId());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ if (shouldShowSystemGestureExclusion()) {
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .registerSystemGestureExclusionListener(mSystemGestureExclusionListener,
+ mContext.getDisplayId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ } else {
+ mSystemGestureExclusion.setEmpty();
}
logInputDevices();
}
@@ -798,6 +804,10 @@
}
}
+ private static boolean shouldShowSystemGestureExclusion() {
+ return SystemProperties.getBoolean("debug.pointerlocation.showexclusion", false);
+ }
+
// HACK
// A quick and dirty string builder implementation optimized for GC.
// Using String.format causes the application grind to a halt when
@@ -920,11 +930,14 @@
@Override
public void onSystemGestureExclusionChanged(int displayId, Region systemGestureExclusion) {
Region exclusion = Region.obtain(systemGestureExclusion);
- getHandler().post(() -> {
- mSystemGestureExclusion.set(exclusion);
- exclusion.recycle();
- invalidate();
- });
+ Handler handler = getHandler();
+ if (handler != null) {
+ handler.post(() -> {
+ mSystemGestureExclusion.set(exclusion);
+ exclusion.recycle();
+ invalidate();
+ });
+ }
}
};
}
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 3a25e67..fc2b7f6 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2027,9 +2027,7 @@
static jint android_media_AudioSystem_removeUidDeviceAffinities(JNIEnv *env, jobject clazz,
jint uid) {
-
- //###
- status_t status = NO_ERROR;//AudioSystem::removeUidDeviceAffinities();
+ status_t status = AudioSystem::removeUidDeviceAffinities((uid_t) uid);
return (jint) nativeToJavaStatus(status);
}
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 28c59db..c5fc9b3 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -49,8 +49,8 @@
namespace android {
constexpr int MAXPACKETSIZE = 8 * 1024;
-// FrameworkListener limits the size of commands to 1024 bytes. TODO: fix this.
-constexpr int MAXCMDSIZE = 1024;
+// FrameworkListener limits the size of commands to 4096 bytes.
+constexpr int MAXCMDSIZE = 4096;
static void throwErrnoException(JNIEnv* env, const char* functionName, int error) {
ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 72e3d349..be9aee4 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -37,14 +37,14 @@
void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName,
jstring driverVersionName, jlong driverVersionCode,
- jlong driverBuildTime, jstring appPackageName) {
+ jlong driverBuildTime, jstring appPackageName, jint vulkanVersion) {
ScopedUtfChars driverPackageNameChars(env, driverPackageName);
ScopedUtfChars driverVersionNameChars(env, driverVersionName);
ScopedUtfChars appPackageNameChars(env, appPackageName);
android::GraphicsEnv::getInstance().setGpuStats(driverPackageNameChars.c_str(),
driverVersionNameChars.c_str(),
driverVersionCode, driverBuildTime,
- appPackageNameChars.c_str());
+ appPackageNameChars.c_str(), vulkanVersion);
}
void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring devOptIn,
@@ -85,15 +85,20 @@
}
}
+void hintActivityLaunch_native(JNIEnv* env, jobject clazz) {
+ android::GraphicsEnv::getInstance().hintActivityLaunch();
+}
+
const JNINativeMethod g_methods[] = {
{ "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
{ "setDriverPathAndSphalLibraries", "(Ljava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPathAndSphalLibraries_native) },
- { "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JJLjava/lang/String;)V", reinterpret_cast<void*>(setGpuStats_native) },
+ { "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JJLjava/lang/String;I)V", reinterpret_cast<void*>(setGpuStats_native) },
{ "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
{ "getShouldUseAngle", "(Ljava/lang/String;)Z", reinterpret_cast<void*>(shouldUseAngle_native) },
{ "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
{ "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native) },
{ "setDebugLayersGLES", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayersGLES_native) },
+ { "hintActivityLaunch", "()V", reinterpret_cast<void*>(hintActivityLaunch_native) },
};
const char* const kGraphicsEnvironmentName = "android/os/GraphicsEnvironment";
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index cb55618..e5b72ca 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -88,7 +88,7 @@
mOwnsBuffer(true),
mHandle(0) {
if (size > 0) {
- mBuffer = malloc(size);
+ mBuffer = calloc(size, 1);
}
}
diff --git a/core/jni/android_util_MemoryIntArray.cpp b/core/jni/android_util_MemoryIntArray.cpp
index b68f9ec..2dfbe3e 100644
--- a/core/jni/android_util_MemoryIntArray.cpp
+++ b/core/jni/android_util_MemoryIntArray.cpp
@@ -142,6 +142,8 @@
jniThrowException(env, "java/io/IOException", "ashmem unpinning failed");
return;
}
+
+ close(fd);
}
static jint android_util_MemoryIntArray_get(JNIEnv* env, jobject clazz,
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index c4c16ee..43c0bbe 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -546,7 +546,7 @@
if (CC_LIKELY(transform.isPureTranslate())) {
// snap/round the computed bounds, so they match the rounding behavior
// of the clear done in SurfaceView#draw().
- bounds.snapToPixelBoundaries();
+ bounds.snapGeometryToPixelBoundaries(false);
} else {
// Conservatively round out so the punched hole (in the ZOrderOnTop = true case)
// doesn't extend beyond the other window
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index ecc9d64..986771d 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -136,8 +136,8 @@
// ColorSpace.Named.SRGB.ordinal() = 0;
static constexpr jint SRGB = 0;
- // ColorSpace.Named.DISPLAY_P3.ordinal() = 6;
- static constexpr jint DISPLAY_P3 = 6;
+ // ColorSpace.Named.DISPLAY_P3.ordinal() = 7;
+ static constexpr jint DISPLAY_P3 = 7;
};
constexpr jint fromDataspaceToNamedColorSpaceValue(const ui::Dataspace dataspace) {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index e7cbf93..f7e9b24 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -986,6 +986,11 @@
SkColorType ct = uirenderer::PixelFormatToColorType(buffer->getPixelFormat());
sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace(bufferItem.mDataSpace);
+ if (cs == nullptr) {
+ // nullptr is treated as SRGB in Skia, thus explicitly use SRGB in order to make sure
+ // the returned bitmap has a color space.
+ cs = SkColorSpace::MakeSRGB();
+ }
sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, ct, cs);
return bitmap::createBitmap(env, bitmap.release(),
android::bitmap::kBitmapCreateFlag_Premultiplied);
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 3d3203e..8ff1691 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -116,9 +116,6 @@
static pid_t gSystemServerPid = 0;
-static const char kIsolatedStorage[] = "persist.sys.isolated_storage";
-static const char kIsolatedStorageSnapshot[] = "sys.isolated_storage_snapshot";
-
static constexpr const char* kZygoteClassName = "com/android/internal/os/Zygote";
static jclass gZygoteClass;
static jmethodID gCallPostForkSystemServerHooks;
@@ -623,249 +620,10 @@
return 0;
}
-static void CreateDir(const std::string& dir,
- mode_t mode, uid_t uid, gid_t gid,
- fail_fn_t fail_fn) {
- if (TEMP_FAILURE_RETRY(access(dir.c_str(), F_OK)) == 0) {
- return;
- } else if (errno != ENOENT) {
- fail_fn(CREATE_ERROR("Failed to stat %s: %s", dir.c_str(), strerror(errno)));
- }
- if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
- fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s: %s",
- dir.c_str(), strerror(errno)));
- }
-}
-
-static void CreatePkgSandboxTarget(userid_t user_id, fail_fn_t fail_fn) {
- ATRACE_CALL();
-
- // Create /mnt/user/0/package
- std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", user_id);
- CreateDir(pkg_sandbox_dir, 0751, AID_ROOT, AID_ROOT, fail_fn);
-
- StringAppendF(&pkg_sandbox_dir, "/package");
- CreateDir(pkg_sandbox_dir, 0755, AID_ROOT, AID_ROOT, fail_fn);
-}
-
-static void BindMount(const std::string& source_dir, const std::string& target_dir,
- fail_fn_t fail_fn) {
- if (TEMP_FAILURE_RETRY(mount(source_dir.c_str(), target_dir.c_str(), nullptr,
- MS_BIND, nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to %s: %s",
- source_dir.c_str(), target_dir.c_str(), strerror(errno)));
- }
-}
-
-static void MountPkgSpecificDir(const std::string& mnt_source_root,
- const std::string& mnt_target_root,
- const std::string& package_name,
- uid_t uid,
- const char* dir_name,
- fail_fn_t fail_fn) {
- ATRACE_CALL();
-
- std::string mnt_source_dir = StringPrintf("%s/Android/%s/%s",
- mnt_source_root.c_str(), dir_name, package_name.c_str());
-
- std::string mnt_target_dir = StringPrintf("%s/Android/%s/%s",
- mnt_target_root.c_str(), dir_name, package_name.c_str());
-
- BindMount(mnt_source_dir, mnt_target_dir, fail_fn);
-}
-
-static void CreateSubDirs(int parent_fd, const std::string& parent_path,
- const std::vector<std::string>& sub_dirs,
- fail_fn_t fail_fn) {
- ATRACE_CALL();
-
- for (auto& dir_name : sub_dirs) {
- struct stat sb;
- if (TEMP_FAILURE_RETRY(fstatat(parent_fd, dir_name.c_str(), &sb, 0)) == 0) {
- if (S_ISDIR(sb.st_mode)) {
- continue;
- } else if (TEMP_FAILURE_RETRY(unlinkat(parent_fd, dir_name.c_str(), 0)) == -1) {
- fail_fn(CREATE_ERROR("Failed to unlinkat on %s/%s: %s",
- parent_path.c_str(), dir_name.c_str(), strerror(errno)));
- }
- } else if (errno != ENOENT) {
- fail_fn(CREATE_ERROR("Failed to fstatat on %s/%s: %s",
- parent_path.c_str(), dir_name.c_str(), strerror(errno)));
- }
- if (TEMP_FAILURE_RETRY(mkdirat(parent_fd, dir_name.c_str(), 0700)) == -1 && errno != EEXIST) {
- fail_fn(CREATE_ERROR("Failed to mkdirat on %s/%s: %s",
- parent_path.c_str(), dir_name.c_str(), strerror(errno)));
- }
- }
-}
-
-static void EnsurePkgSpecificDirs(const std::string& path,
- const std::vector<std::string>& package_names,
- bool create_sandbox_dir,
- fail_fn_t fail_fn) {
- ATRACE_CALL();
-
- std::string android_dir = StringPrintf("%s/Android", path.c_str());
- android::base::unique_fd android_fd(open(android_dir.c_str(),
- O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- if (android_fd.get() < 0) {
- if (errno == ENOENT || errno == ENOTDIR) {
- if (errno == ENOTDIR && TEMP_FAILURE_RETRY(unlink(android_dir.c_str())) == -1) {
- fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
- android_dir.c_str(), strerror(errno)));
- }
- if (TEMP_FAILURE_RETRY(mkdir(android_dir.c_str(), 0700)) == -1
- && errno != EEXIST) {
- fail_fn(CREATE_ERROR("Failed to mkdir %s: %s",
- android_dir.c_str(), strerror(errno)));
- }
- android_fd.reset(open(android_dir.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- }
-
- if (android_fd.get() < 0) {
- fail_fn(CREATE_ERROR("Failed to open %s: %s", android_dir.c_str(), strerror(errno)));
- }
- }
-
- std::vector<std::string> data_media_obb_dirs = {"data", "media", "obb"};
- if (create_sandbox_dir) {
- data_media_obb_dirs.push_back("sandbox");
- }
- CreateSubDirs(android_fd.get(), android_dir, data_media_obb_dirs, fail_fn);
- if (create_sandbox_dir) {
- data_media_obb_dirs.pop_back();
- }
- for (auto& dir_name : data_media_obb_dirs) {
- std::string data_dir = StringPrintf("%s/%s", android_dir.c_str(), dir_name.c_str());
- android::base::unique_fd data_fd(openat(android_fd, dir_name.c_str(),
- O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- if (data_fd.get() < 0) {
- fail_fn(CREATE_ERROR("Failed to openat %s/%s: %s",
- android_dir.c_str(), dir_name.c_str(), strerror(errno)));
- }
- CreateSubDirs(data_fd.get(), data_dir, package_names, fail_fn);
- }
-}
-
-static void CreatePkgSandboxSource(const std::string& sandbox_source, fail_fn_t fail_fn) {
- ATRACE_CALL();
-
- struct stat sb;
- if (TEMP_FAILURE_RETRY(stat(sandbox_source.c_str(), &sb)) == 0) {
- if (S_ISDIR(sb.st_mode)) {
- return;
- } else if (TEMP_FAILURE_RETRY(unlink(sandbox_source.c_str())) == -1) {
- fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
- sandbox_source.c_str(), strerror(errno)));
- }
- } else if (errno != ENOENT) {
- fail_fn(CREATE_ERROR("Failed to stat %s: %s",
- sandbox_source.c_str(), strerror(errno)));
- }
- if (TEMP_FAILURE_RETRY(mkdir(sandbox_source.c_str(), 0700)) == -1 && errno != EEXIST) {
- fail_fn(CREATE_ERROR("Failed to mkdir %s: %s",
- sandbox_source.c_str(), strerror(errno)));
- }
-}
-
-static void PreparePkgSpecificDirs(const std::vector<std::string>& package_names,
- bool mount_all_obbs, const std::string& sandbox_id,
- userid_t user_id, uid_t uid, fail_fn_t fail_fn) {
- ATRACE_CALL();
-
- std::unique_ptr<DIR, decltype(&closedir)> dirp(opendir("/storage"), closedir);
- if (!dirp) {
- fail_fn(CREATE_ERROR("Failed to opendir /storage: %s", strerror(errno)));
- }
- struct dirent* ent;
- while ((ent = readdir(dirp.get()))) {
- if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "self")) {
- continue;
- }
- std::string label(ent->d_name);
-
- std::string mnt_source = StringPrintf("/mnt/runtime/write/%s", label.c_str());
- std::string mnt_target = StringPrintf("/storage/%s", label.c_str());
- if (label == "emulated") {
- StringAppendF(&mnt_source, "/%d", user_id);
- StringAppendF(&mnt_target, "/%d", user_id);
- }
-
- if (TEMP_FAILURE_RETRY(access(mnt_source.c_str(), F_OK)) == -1) {
- ALOGE("Can't access %s: %s", mnt_source.c_str(), strerror(errno));
- continue;
- } else if (TEMP_FAILURE_RETRY(access(mnt_target.c_str(), F_OK)) == -1) {
- ALOGE("Can't access %s: %s", mnt_target.c_str(), strerror(errno));
- continue;
- }
-
- // Ensure /mnt/runtime/write/emulated/0/Android/{data,media,obb}
- EnsurePkgSpecificDirs(mnt_source, package_names, true, fail_fn);
-
- std::string sandbox_source = StringPrintf("%s/Android/sandbox/%s",
- mnt_source.c_str(), sandbox_id.c_str());
- CreatePkgSandboxSource(sandbox_source, fail_fn);
- BindMount(sandbox_source, mnt_target, fail_fn);
-
- // Ensure /storage/emulated/0/Android/{data,media,obb}
- EnsurePkgSpecificDirs(mnt_target, package_names, false, fail_fn);
- for (auto& package : package_names) {
- MountPkgSpecificDir(mnt_source, mnt_target, package, uid, "data", fail_fn);
- MountPkgSpecificDir(mnt_source, mnt_target, package, uid, "media", fail_fn);
- if (!mount_all_obbs) {
- MountPkgSpecificDir(mnt_source, mnt_target, package, uid, "obb", fail_fn);
- }
- }
-
- if (mount_all_obbs) {
- StringAppendF(&mnt_source, "/Android/obb");
- StringAppendF(&mnt_target, "/Android/obb");
- BindMount(mnt_source, mnt_target, fail_fn);
- }
- }
-}
-
-static void HandleMountModeInstaller(int mount_mode,
- userid_t user_id,
- const std::string& sandbox_id,
- fail_fn_t fail_fn) {
- ATRACE_CALL();
-
- std::string obb_mount_dir = StringPrintf("/mnt/user/%d/obb_mount", user_id);
- std::string obb_mount_file = StringPrintf("%s/%s", obb_mount_dir.c_str(), sandbox_id.c_str());
- if (mount_mode == MOUNT_EXTERNAL_INSTALLER) {
- if (TEMP_FAILURE_RETRY(access(obb_mount_file.c_str(), F_OK)) != -1) {
- return;
- } else if (errno != ENOENT) {
- fail_fn(CREATE_ERROR("Failed to access %s: %s", obb_mount_file.c_str(), strerror(errno)));
- }
- if (fs_prepare_dir(obb_mount_dir.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) {
- fail_fn(CREATE_ERROR("Failed to fs_prepare_dir %s: %s",
- obb_mount_dir.c_str(), strerror(errno)));
- }
- const android::base::unique_fd fd(TEMP_FAILURE_RETRY(
- open(obb_mount_file.c_str(), O_RDWR | O_CREAT, 0600)));
- if (fd.get() < 0) {
- fail_fn(CREATE_ERROR("Failed to create %s: %s", obb_mount_file.c_str(), strerror(errno)));
- }
- } else {
- if (TEMP_FAILURE_RETRY(access(obb_mount_file.c_str(), F_OK)) != -1) {
- if (TEMP_FAILURE_RETRY(unlink(obb_mount_file.c_str())) == -1) {
- fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
- obb_mount_dir.c_str(), strerror(errno)));
- }
- } else if (errno != ENOENT) {
- fail_fn(CREATE_ERROR("Failed to access %s: %s", obb_mount_file.c_str(), strerror(errno)));
- }
- }
-}
-
// Create a private mount namespace and bind mount appropriate emulated
// storage for the given user.
static void MountEmulatedStorage(uid_t uid, jint mount_mode,
- bool force_mount_namespace, const std::string& package_name,
- const std::vector<std::string>& packages_for_uid,
- const std::string& sandbox_id,
+ bool force_mount_namespace,
fail_fn_t fail_fn) {
// See storage config details at http://source.android.com/tech/storage/
ATRACE_CALL();
@@ -896,73 +654,25 @@
return;
}
- if (/* DISABLES CODE */ (false)
- && GetBoolProperty(kIsolatedStorageSnapshot, GetBoolProperty(kIsolatedStorage, true))) {
- if (mount_mode == MOUNT_EXTERNAL_FULL || mount_mode == MOUNT_EXTERNAL_LEGACY) {
- storage_source = (mount_mode == MOUNT_EXTERNAL_FULL)
- ? "/mnt/runtime/full" : "/mnt/runtime/write";
- if (TEMP_FAILURE_RETRY(mount(storage_source.string(), "/storage",
- NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
- storage_source.string(),
- strerror(errno)));
- }
+ if (TEMP_FAILURE_RETRY(mount(storage_source.string(), "/storage", nullptr,
+ MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
+ storage_source.string(),
+ strerror(errno)));
+ }
- // Mount user-specific symlink helper into place
- userid_t user_id = multiuser_get_user_id(uid);
- const String8 user_source(String8::format("/mnt/user/%d", user_id));
- if (fs_prepare_dir(user_source.string(), 0751, 0, 0) == -1) {
- fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s (%s)",
- user_source.string(), strerror(errno)));
- }
+ // Mount user-specific symlink helper into place
+ userid_t user_id = multiuser_get_user_id(uid);
+ const String8 user_source(String8::format("/mnt/user/%d", user_id));
+ if (fs_prepare_dir(user_source.string(), 0751, 0, 0) == -1) {
+ fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s",
+ user_source.string()));
+ }
- if (TEMP_FAILURE_RETRY(mount(user_source.string(), "/storage/self", nullptr, MS_BIND,
- nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage/self: %s",
- user_source.string(),
- strerror(errno)));
- }
- } else {
- if (package_name.empty() || sandbox_id.empty()) {
- return;
- }
-
- userid_t user_id = multiuser_get_user_id(uid);
- CreatePkgSandboxTarget(user_id, fail_fn);
-
- std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d/package", user_id);
- if (TEMP_FAILURE_RETRY(mount(pkg_sandbox_dir.c_str(), "/storage",
- nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
- pkg_sandbox_dir.c_str(), strerror(errno)));
- }
-
- HandleMountModeInstaller(mount_mode, user_id, sandbox_id, fail_fn);
-
- PreparePkgSpecificDirs(packages_for_uid,
- mount_mode == MOUNT_EXTERNAL_INSTALLER, sandbox_id, user_id, uid, fail_fn);
- }
- } else {
- if (TEMP_FAILURE_RETRY(mount(storage_source.string(), "/storage", nullptr,
- MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
- storage_source.string(),
- strerror(errno)));
- }
-
- // Mount user-specific symlink helper into place
- userid_t user_id = multiuser_get_user_id(uid);
- const String8 user_source(String8::format("/mnt/user/%d", user_id));
- if (fs_prepare_dir(user_source.string(), 0751, 0, 0) == -1) {
- fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s",
- user_source.string()));
- }
-
- if (TEMP_FAILURE_RETRY(mount(user_source.string(), "/storage/self",
- nullptr, MS_BIND, nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage/self: %s",
- user_source.string(), strerror(errno)));
- }
+ if (TEMP_FAILURE_RETRY(mount(user_source.string(), "/storage/self",
+ nullptr, MS_BIND, nullptr)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mount %s to /storage/self: %s",
+ user_source.string(), strerror(errno)));
}
}
@@ -1136,45 +846,6 @@
}
/**
- * A helper method for converting managed string arrays to native vectors. A
- * fatal error is generated if a problem is encountered in extracting a non-null array.
- *
- * @param env Managed runtime environment
- * @param process_name A native representation of the process name
- * @param managed_process_name A managed representation of the process name
- * @param managed_array The managed string array to extract
- *
- * @return An empty option if the managed array is null. A optional-wrapped
- * vector otherwise.
- */
-static std::optional<std::vector<std::string>> ExtractJStringArray(JNIEnv* env,
- const char* process_name,
- jstring managed_process_name,
- jobjectArray managed_array) {
- if (managed_array == nullptr) {
- return std::nullopt;
- } else {
- jsize element_count = env->GetArrayLength(managed_array);
- std::vector<std::string> native_string_vector;
- native_string_vector.reserve(element_count);
-
- for (jsize array_index = 0; array_index < element_count; ++array_index) {
- jstring managed_string = (jstring) env->GetObjectArrayElement(managed_array, array_index);
- auto native_string = ExtractJString(env, process_name, managed_process_name, managed_string);
-
- if (LIKELY(native_string.has_value())) {
- native_string_vector.emplace_back(std::move(native_string.value()));
- } else {
- ZygoteFailure(env, process_name, managed_process_name,
- "Null string found in managed string array.");
- }
- }
-
- return std::move(native_string_vector);
- }
-}
-
-/**
* A utility function for blocking signals.
*
* @param signum Signal number to block
@@ -1287,9 +958,7 @@
jint mount_external, jstring managed_se_info,
jstring managed_nice_name, bool is_system_server,
bool is_child_zygote, jstring managed_instruction_set,
- jstring managed_app_data_dir, jstring managed_package_name,
- jobjectArray managed_pacakges_for_uid,
- jstring managed_sandbox_id) {
+ jstring managed_app_data_dir) {
const char* process_name = is_system_server ? "system_server" : "zygote";
auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
@@ -1298,8 +967,6 @@
auto nice_name = extract_fn(managed_nice_name);
auto instruction_set = extract_fn(managed_instruction_set);
auto app_data_dir = extract_fn(managed_app_data_dir);
- auto package_name = extract_fn(managed_package_name);
- auto sandbox_id = extract_fn(managed_sandbox_id);
// Keep capabilities across UID change, unless we're staying root.
if (uid != 0) {
@@ -1325,20 +992,7 @@
ALOGW("Native bridge will not be used because managed_app_data_dir == nullptr.");
}
- if (!package_name.has_value()) {
- if (is_system_server) {
- package_name.emplace("android");
- } else {
- package_name.emplace("");
- }
- }
-
- std::vector<std::string> packages_for_uid =
- ExtractJStringArray(env, process_name, managed_nice_name, managed_pacakges_for_uid).
- value_or(std::vector<std::string>());
-
- MountEmulatedStorage(uid, mount_external, use_native_bridge, package_name.value(),
- packages_for_uid, sandbox_id.value_or(""), fail_fn);
+ MountEmulatedStorage(uid, mount_external, use_native_bridge, fail_fn);
// If this zygote isn't root, it won't be able to create a process group,
// since the directory is owned by root.
@@ -1681,8 +1335,7 @@
jint runtime_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring nice_name,
jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
- jstring instruction_set, jstring app_data_dir, jstring package_name,
- jobjectArray packages_for_uid, jstring sandbox_id) {
+ jstring instruction_set, jstring app_data_dir) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
if (UNLIKELY(managed_fds_to_close == nullptr)) {
@@ -1713,8 +1366,7 @@
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
capabilities, capabilities,
mount_external, se_info, nice_name, false,
- is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
- package_name, packages_for_uid, sandbox_id);
+ is_child_zygote == JNI_TRUE, instruction_set, app_data_dir);
}
return pid;
}
@@ -1740,7 +1392,7 @@
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
permitted_capabilities, effective_capabilities,
MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
- false, nullptr, nullptr, nullptr, nullptr, nullptr);
+ false, nullptr, nullptr);
} else if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
@@ -1859,16 +1511,13 @@
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint runtime_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring nice_name,
- jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir,
- jstring package_name, jobjectArray packages_for_uid,
- jstring sandbox_id) {
+ jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
capabilities, capabilities,
mount_external, se_info, nice_name, false,
- is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
- package_name, packages_for_uid, sandbox_id);
+ is_child_zygote == JNI_TRUE, instruction_set, app_data_dir);
}
/**
@@ -2031,7 +1680,7 @@
static const JNINativeMethod gMethods[] = {
{ "nativeForkAndSpecialize",
- "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)I",
+ "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
(void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
(void *) com_android_internal_os_Zygote_nativeForkSystemServer },
@@ -2044,7 +1693,7 @@
{ "nativeForkUsap", "(II[I)I",
(void *) com_android_internal_os_Zygote_nativeForkUsap },
{ "nativeSpecializeAppProcess",
- "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V",
+ "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V",
(void *) com_android_internal_os_Zygote_nativeSpecializeAppProcess },
{ "nativeInitNativeState", "(Z)V",
(void *) com_android_internal_os_Zygote_nativeInitNativeState },
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 9cffb2b..36eb4c4 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -666,6 +666,11 @@
//ACTION: Log result for each card's eligibility check
ACTION_CONTEXTUAL_CARD_ELIGIBILITY = 1686;
+ // ACTION: Display white balance setting enabled or disabled.
+ // CATEGORY: SETTINGS
+ // OS: Q
+ ACTION_DISPLAY_WHITE_BALANCE_SETTING_CHANGED = 1703;
+
// ACTION: Share a Wi-Fi network by generating a QR code
ACTION_SETTINGS_SHARE_WIFI_QR_CODE = 1710;
@@ -674,6 +679,15 @@
// ACTION: Share Wi-Fi hotspot by generating a QR code
ACTION_SETTINGS_SHARE_WIFI_HOTSPOT_QR_CODE = 1712;
+
+ // ACTION: Settings > Initialize Search bar > Verify Slice > Invalid data
+ ACTION_VERIFY_SLICE_ERROR_INVALID_DATA = 1725;
+
+ // ACTION: Settings > Initialize Search bar > Verify Slice > Parsing error
+ ACTION_VERIFY_SLICE_PARSING_ERROR = 1726;
+
+ // ACTION: Settings > Initialize Search bar > Verify Slice > Other exception
+ ACTION_VERIFY_SLICE_OTHER_EXCEPTION = 1727;
}
/**
@@ -2341,11 +2355,6 @@
// Open: Settings > app > bubble settings > confirmation dialog
DIALOG_APP_BUBBLE_SETTINGS = 1702;
- // ACTION: Display white balance setting enabled or disabled.
- // CATEGORY: SETTINGS
- // OS: Q
- ACTION_DISPLAY_WHITE_BALANCE_SETTING_CHANGED = 1703;
-
// OPEN: Settings > Pick SIM dialog
DIALOG_SIM_LIST = 1707;
@@ -2361,4 +2370,12 @@
// OPEN: Settings > Network & internet > Mobile network > Delete sim > (answer yes to
// confirmation)
DIALOG_DELETE_SIM_PROGRESS = 1714;
+
+ // Settings > Apps and notifications > Notifications > Gentle notifications
+ GENTLE_NOTIFICATIONS_SCREEN = 1715;
+
+ // OPEN: Settings > System > Gestures > Global Actions Panel
+ // CATEGORY: SETTINGS
+ // OS: Q
+ GLOBAL_ACTIONS_PANEL_SETTINGS = 1800;
}
diff --git a/core/proto/android/content/locale.proto b/core/proto/android/content/locale.proto
index d8af754..bae6ec1 100644
--- a/core/proto/android/content/locale.proto
+++ b/core/proto/android/content/locale.proto
@@ -27,5 +27,6 @@
optional string language = 1;
optional string country = 2;
optional string variant = 3;
+ optional string script = 4;
}
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index dbd2191..e6ae226 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -159,6 +159,9 @@
optional int32 surface_size = 14 [deprecated=true];
optional string focused_app = 15;
optional AppTransitionProto app_transition = 16;
+ repeated IdentifierProto opening_apps = 17;
+ repeated IdentifierProto closing_apps = 18;
+ repeated IdentifierProto changing_apps = 19;
}
/* represents DisplayFrames */
diff --git a/core/proto/android/service/adb.proto b/core/proto/android/service/adb.proto
index 493f9b8..549d30c 100644
--- a/core/proto/android/service/adb.proto
+++ b/core/proto/android/service/adb.proto
@@ -35,4 +35,5 @@
optional string last_key_recevied = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
optional string user_keys = 3 [ (android.privacy).dest = DEST_LOCAL ];
optional string system_keys = 4 [ (android.privacy).dest = DEST_LOCAL ];
+ optional string keystore = 5 [ (android.privacy).dest = DEST_LOCAL ];
}
diff --git a/core/proto/android/stats/connectivity/resolv_stats.proto b/core/proto/android/stats/connectivity/resolv_stats.proto
deleted file mode 100644
index 43eb673..0000000
--- a/core/proto/android/stats/connectivity/resolv_stats.proto
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-syntax = "proto2";
-package android.stats.connectivity;
-import "frameworks/base/core/proto/android/net/networkcapabilities.proto";
-
-enum EventType {
- EVENT_UNKNOWN = 0;
- EVENT_GETADDRINFO = 1;
- EVENT_GETHOSTBYNAME = 2;
- EVENT_GETHOSTBYADDR = 3;
- EVENT_RES_NSEND = 4;
-}
-
-enum PrivateDnsModes {
- OFF = 0;
- OPPORTUNISTIC = 1;
- STRICT = 2;
-}
-// The return value of the DNS resolver for each DNS lookups.
-// bionic/libc/include/netdb.h
-// system/netd/resolv/include/netd_resolv/resolv.h
-enum ReturnCode {
- RC_EAI_NO_ERROR = 0;
- RC_EAI_ADDRFAMILY = 1;
- RC_EAI_AGAIN = 2;
- RC_EAI_BADFLAGS = 3;
- RC_EAI_FAIL = 4;
- RC_EAI_FAMILY = 5;
- RC_EAI_MEMORY = 6;
- RC_EAI_NODATA = 7;
- RC_EAI_NONAME = 8;
- RC_EAI_SERVICE = 9;
- RC_EAI_SOCKTYPE = 10;
- RC_EAI_SYSTEM = 11;
- RC_EAI_BADHINTS = 12;
- RC_EAI_PROTOCOL = 13;
- RC_EAI_OVERFLOW = 14;
- RC_RESOLV_TIMEOUT = 255;
- RC_EAI_MAX = 256;
-}
-
-
-enum NsRcode {
- ns_r_noerror = 0; // No error occurred.
- ns_r_formerr = 1; // Format error.
- ns_r_servfail = 2; // Server failure.
- ns_r_nxdomain = 3; // Name error.
- ns_r_notimpl = 4; // Unimplemented.
- ns_r_refused = 5; // Operation refused.
- // these are for BIND_UPDATE
- ns_r_yxdomain = 6; // Name exists
- ns_r_yxrrset = 7; // RRset exists
- ns_r_nxrrset = 8; // RRset does not exist
- ns_r_notauth = 9; // Not authoritative for zone
- ns_r_notzone = 10; // Zone of record different from zone section
- ns_r_max = 11;
- // The following are EDNS extended rcodes
- ns_r_badvers = 16;
- // The following are TSIG errors
- //ns_r_badsig = 16,
- ns_r_badkey = 17;
- ns_r_badtime = 18;
-}
-
-// Currently defined type values for resources and queries.
-enum NsType {
- ns_t_invalid = 0; // Cookie.
- ns_t_a = 1; // Host address.
- ns_t_ns = 2; // Authoritative server.
- ns_t_md = 3; // Mail destination.
- ns_t_mf = 4; // Mail forwarder.
- ns_t_cname = 5; // Canonical name.
- ns_t_soa = 6; // Start of authority zone.
- ns_t_mb = 7; // Mailbox domain name.
- ns_t_mg = 8; // Mail group member.
- ns_t_mr = 9; // Mail rename name.
- ns_t_null = 10; // Null resource record.
- ns_t_wks = 11; // Well known service.
- ns_t_ptr = 12; // Domain name pointer.
- ns_t_hinfo = 13; // Host information.
- ns_t_minfo = 14; // Mailbox information.
- ns_t_mx = 15; // Mail routing information.
- ns_t_txt = 16; // Text strings.
- ns_t_rp = 17; // Responsible person.
- ns_t_afsdb = 18; // AFS cell database.
- ns_t_x25 = 19; // X_25 calling address.
- ns_t_isdn = 20; // ISDN calling address.
- ns_t_rt = 21; // Router.
- ns_t_nsap = 22; // NSAP address.
- ns_t_nsap_ptr = 23; // Reverse NSAP lookup (deprecated).
- ns_t_sig = 24; // Security signature.
- ns_t_key = 25; // Security key.
- ns_t_px = 26; // X.400 mail mapping.
- ns_t_gpos = 27; // Geographical position (withdrawn).
- ns_t_aaaa = 28; // IPv6 Address.
- ns_t_loc = 29; // Location Information.
- ns_t_nxt = 30; // Next domain (security).
- ns_t_eid = 31; // Endpoint identifier.
- ns_t_nimloc = 32; // Nimrod Locator.
- ns_t_srv = 33; // Server Selection.
- ns_t_atma = 34; // ATM Address
- ns_t_naptr = 35; // Naming Authority PoinTeR
- ns_t_kx = 36; // Key Exchange
- ns_t_cert = 37; // Certification record
- ns_t_a6 = 38; // IPv6 address (experimental)
- ns_t_dname = 39; // Non-terminal DNAME
- ns_t_sink = 40; // Kitchen sink (experimentatl)
- ns_t_opt = 41; // EDNS0 option (meta-RR)
- ns_t_apl = 42; // Address prefix list (RFC 3123)
- ns_t_ds = 43; // Delegation Signer
- ns_t_sshfp = 44; // SSH Fingerprint
- ns_t_ipseckey = 45; // IPSEC Key
- ns_t_rrsig = 46; // RRset Signature
- ns_t_nsec = 47; // Negative security
- ns_t_dnskey = 48; // DNS Key
- ns_t_dhcid = 49; // Dynamic host configuratin identifier
- ns_t_nsec3 = 50; // Negative security type 3
- ns_t_nsec3param = 51;// Negative security type 3 parameters
- ns_t_hip = 55; // Host Identity Protocol
- ns_t_spf = 99; // Sender Policy Framework
- ns_t_tkey = 249; // Transaction key
- ns_t_tsig = 250; // Transaction signature.
- ns_t_ixfr = 251; // Incremental zone transfer.
- ns_t_axfr = 252; // Transfer zone of authority.
- ns_t_mailb = 253; // Transfer mailbox records.
- ns_t_maila = 254; // Transfer mail agent records.
- ns_t_any = 255; // Wildcard match.
- ns_t_zxfr = 256; // BIND-specific, nonstandard.
- ns_t_dlv = 32769; // DNSSEC look-aside validatation.
- ns_t_max = 65536;
-}
-
-enum IpVersion {
- IPV4 = 0;
- IPV6 = 1;
- MIXED = 2;
-}
-
-enum TransportType {
- UDP = 0;
- TCP = 1;
- DOT = 2;
- DOT_UDP = 3;
- DOT_TCP = 4;
-}
-
-message DnsQueryEvent {
- optional NsRcode rrcode = 1;
- optional NsType rrtype = 2;
- optional bool cache_hit = 3;
- optional IpVersion ipversion = 4;
- optional TransportType transport = 5;
- optional int32 packet_retransmits = 6; // Used only by the UDP transport
- optional int32 reconnects = 7; // Used only by TCP and DOT
- optional int32 latency_micros = 8;
- optional int32 active_experiments = 9;
- optional android.net.NetworkCapabilitiesProto.Transport network_type = 10;
-}
-
-message DnsQueryEventRe {
- repeated DnsQueryEvent dns_query_event = 1;
-}
-
-
-message DnsCallEvent {
-
-}
-
diff --git a/core/proto/android/stats/dnsresolver/Android.bp b/core/proto/android/stats/dnsresolver/Android.bp
new file mode 100644
index 0000000..0b5aa86
--- /dev/null
+++ b/core/proto/android/stats/dnsresolver/Android.bp
@@ -0,0 +1,25 @@
+// Copyright (C) 2019 The Android Open 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.
+
+java_library_static {
+ name: "dnsresolverprotosnano",
+ proto: {
+ type: "nano",
+ },
+ srcs: [
+ "dns_resolver.proto",
+ ],
+ sdk_version: "system_current",
+ no_framework_libs: true,
+}
diff --git a/core/proto/android/stats/dnsresolver/dns_resolver.proto b/core/proto/android/stats/dnsresolver/dns_resolver.proto
new file mode 100644
index 0000000..af6fea0
--- /dev/null
+++ b/core/proto/android/stats/dnsresolver/dns_resolver.proto
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+syntax = "proto2";
+package android.stats.dnsresolver;
+
+enum EventType {
+ EVENT_UNKNOWN = 0;
+ EVENT_GETADDRINFO = 1;
+ EVENT_GETHOSTBYNAME = 2;
+ EVENT_GETHOSTBYADDR = 3;
+ EVENT_RES_NSEND = 4;
+}
+
+// The return value of the DNS resolver for each DNS lookups.
+// bionic/libc/include/netdb.h
+// system/netd/resolv/include/netd_resolv/resolv.h
+enum ReturnCode {
+ RC_EAI_NO_ERROR = 0;
+ RC_EAI_ADDRFAMILY = 1;
+ RC_EAI_AGAIN = 2;
+ RC_EAI_BADFLAGS = 3;
+ RC_EAI_FAIL = 4;
+ RC_EAI_FAMILY = 5;
+ RC_EAI_MEMORY = 6;
+ RC_EAI_NODATA = 7;
+ RC_EAI_NONAME = 8;
+ RC_EAI_SERVICE = 9;
+ RC_EAI_SOCKTYPE = 10;
+ RC_EAI_SYSTEM = 11;
+ RC_EAI_BADHINTS = 12;
+ RC_EAI_PROTOCOL = 13;
+ RC_EAI_OVERFLOW = 14;
+ RC_RESOLV_TIMEOUT = 255;
+ RC_EAI_MAX = 256;
+}
+
+enum NsRcode {
+ NS_R_NO_ERROR = 0; // No error occurred.
+ NS_R_FORMERR = 1; // Format error.
+ NS_R_SERVFAIL = 2; // Server failure.
+ NS_R_NXDOMAIN = 3; // Name error.
+ NS_R_NOTIMPL = 4; // Unimplemented.
+ NS_R_REFUSED = 5; // Operation refused.
+ // these are for BIND_UPDATE
+ NS_R_YXDOMAIN = 6; // Name exists
+ NS_R_YXRRSET = 7; // RRset exists
+ NS_R_NXRRSET = 8; // RRset does not exist
+ NS_R_NOTAUTH = 9; // Not authoritative for zone
+ NS_R_NOTZONE = 10; // Zone of record different from zone section
+ NS_R_MAX = 11;
+ // The following are EDNS extended rcodes
+ NS_R_BADVERS = 16;
+ // The following are TSIG errors
+ // NS_R_BADSIG = 16,
+ NS_R_BADKEY = 17;
+ NS_R_BADTIME = 18;
+}
+
+// Currently defined type values for resources and queries.
+enum NsType {
+ NS_T_INVALID = 0; // Cookie.
+ NS_T_A = 1; // Host address.
+ NS_T_NS = 2; // Authoritative server.
+ NS_T_MD = 3; // Mail destination.
+ NS_T_MF = 4; // Mail forwarder.
+ NS_T_CNAME = 5; // Canonical name.
+ NS_T_SOA = 6; // Start of authority zone.
+ NS_T_MB = 7; // Mailbox domain name.
+ NS_T_MG = 8; // Mail group member.
+ NS_T_MR = 9; // Mail rename name.
+ NS_T_NULL = 10; // Null resource record.
+ NS_T_WKS = 11; // Well known service.
+ NS_T_PTR = 12; // Domain name pointer.
+ NS_T_HINFO = 13; // Host information.
+ NS_T_MINFO = 14; // Mailbox information.
+ NS_T_MX = 15; // Mail routing information.
+ NS_T_TXT = 16; // Text strings.
+ NS_T_RP = 17; // Responsible person.
+ NS_T_AFSDB = 18; // AFS cell database.
+ NS_T_X25 = 19; // X_25 calling address.
+ NS_T_ISDN = 20; // ISDN calling address.
+ NS_T_RT = 21; // Router.
+ NS_T_NSAP = 22; // NSAP address.
+ NS_T_NSAP_PTR = 23; // Reverse NSAP lookup (deprecated).
+ NS_T_SIG = 24; // Security signature.
+ NS_T_KEY = 25; // Security key.
+ NS_T_PX = 26; // X.400 mail mapping.
+ NS_T_GPOS = 27; // Geographical position (withdrawn).
+ NS_T_AAAA = 28; // IPv6 Address.
+ NS_T_LOC = 29; // Location Information.
+ NS_T_NXT = 30; // Next domain (security).
+ NS_T_EID = 31; // Endpoint identifier.
+ NS_T_NIMLOC = 32; // Nimrod Locator.
+ NS_T_SRV = 33; // Server Selection.
+ NS_T_ATMA = 34; // ATM Address
+ NS_T_NAPTR = 35; // Naming Authority PoinTeR
+ NS_T_KX = 36; // Key Exchange
+ NS_T_CERT = 37; // Certification record
+ NS_T_A6 = 38; // IPv6 address (experimental)
+ NS_T_DNAME = 39; // Non-terminal DNAME
+ NS_T_SINK = 40; // Kitchen sink (experimentatl)
+ NS_T_OPT = 41; // EDNS0 option (meta-RR)
+ NS_T_APL = 42; // Address prefix list (RFC 3123)
+ NS_T_DS = 43; // Delegation Signer
+ NS_T_SSHFP = 44; // SSH Fingerprint
+ NS_T_IPSECKEY = 45; // IPSEC Key
+ NS_T_RRSIG = 46; // RRset Signature
+ NS_T_NSEC = 47; // Negative security
+ NS_T_DNSKEY = 48; // DNS Key
+ NS_T_DHCID = 49; // Dynamic host configuratin identifier
+ NS_T_NSEC3 = 50; // Negative security type 3
+ NS_T_NSEC3PARAM = 51; // Negative security type 3 parameters
+ NS_T_HIP = 55; // Host Identity Protocol
+ NS_T_SPF = 99; // Sender Policy Framework
+ NS_T_TKEY = 249; // Transaction key
+ NS_T_TSIG = 250; // Transaction signature.
+ NS_T_IXFR = 251; // Incremental zone transfer.
+ NS_T_AXFR = 252; // Transfer zone of authority.
+ NS_T_MAILB = 253; // Transfer mailbox records.
+ NS_T_MAILA = 254; // Transfer mail agent records.
+ NS_T_ANY = 255; // Wildcard match.
+ NS_T_ZXFR = 256; // BIND-specific, nonstandard.
+ NS_T_DLV = 32769; // DNSSEC look-aside validatation.
+ NS_T_MAX = 65536;
+}
+
+enum IpVersion {
+ IV_UNKNOWN = 0;
+ IV_IPV4 = 1;
+ IV_IPV6 = 2;
+}
+
+enum TransportType {
+ TT_UNKNOWN = 0;
+ TT_UDP = 1;
+ TT_TCP = 2;
+ TT_DOT = 3;
+}
+
+enum PrivateDnsModes {
+ PDM_UNKNOWN = 0;
+ PDM_OFF = 1;
+ PDM_OPPORTUNISTIC = 2;
+ PDM_STRICT = 3;
+}
+
+enum Transport {
+ // Indicates this network uses a Cellular transport.
+ TRANSPORT_DEFAULT = 0; // TRANSPORT_CELLULAR
+ // Indicates this network uses a Wi-Fi transport.
+ TRANSPORT_WIFI = 1;
+ // Indicates this network uses a Bluetooth transport.
+ TRANSPORT_BLUETOOTH = 2;
+ // Indicates this network uses an Ethernet transport.
+ TRANSPORT_ETHERNET = 3;
+ // Indicates this network uses a VPN transport.
+ TRANSPORT_VPN = 4;
+ // Indicates this network uses a Wi-Fi Aware transport.
+ TRANSPORT_WIFI_AWARE = 5;
+ // Indicates this network uses a LoWPAN transport.
+ TRANSPORT_LOWPAN = 6;
+}
+
+enum CacheStatus{
+ // the cache can't handle that kind of queries.
+ // or the answer buffer is too small.
+ CS_UNSUPPORTED = 0;
+ // the cache doesn't know about this query.
+ CS_NOTFOUND = 1;
+ // the cache found the answer.
+ CS_FOUND = 2;
+ // Don't do anything on cache.
+ CS_SKIP = 3;
+}
+
+message DnsQueryEvent {
+ optional android.stats.dnsresolver.NsRcode rcode = 1;
+
+ optional android.stats.dnsresolver.NsType type = 2;
+
+ optional android.stats.dnsresolver.CacheStatus cache_hit = 3;
+
+ optional android.stats.dnsresolver.IpVersion ip_version = 4;
+
+ optional android.stats.dnsresolver.TransportType transport = 5;
+
+ // Number of DNS query retry times
+ optional int32 retry_times = 6;
+
+ // Ordinal number of name server.
+ optional int32 dns_server_count = 7;
+
+ // Used only by TCP and DOT. True for new connections.
+ optional bool connected = 8;
+
+ optional int32 latency_micros = 9;
+}
+
+message DnsQueryEvents {
+ repeated DnsQueryEvent dns_query_event = 1;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8714bf2..b634bb2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -43,6 +43,7 @@
<protected-broadcast android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_CHANGED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_ENABLE_ROLLBACK" />
+ <protected-broadcast android:name="android.intent.action.CANCEL_ENABLE_ROLLBACK" />
<protected-broadcast android:name="android.intent.action.ROLLBACK_COMMITTED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_RESTARTED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
@@ -4212,6 +4213,15 @@
android:description="@string/permdesc_bindCarrierServices"
android:protectionLevel="signature|privileged" />
+ <!--
+ Allows the holder to start the permission usage screen for an app.
+ <p>Protection level: signature|installer
+ -->
+ <permission android:name="android.permission.START_VIEW_PERMISSION_USAGE"
+ android:label="@string/permlab_startViewPermissionUsage"
+ android:description="@string/permdesc_startViewPermissionUsage"
+ android:protectionLevel="signature|installer" />
+
<!-- Allows an application to query whether DO_NOT_ASK_CREDENTIALS_ON_BOOT
flag is set.
@hide -->
diff --git a/core/res/res/anim/ic_bluetooth_transient_animation_0.xml b/core/res/res/anim/ic_bluetooth_transient_animation_0.xml
new file mode 100644
index 0000000..f14cfcf
--- /dev/null
+++ b/core/res/res/anim/ic_bluetooth_transient_animation_0.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="0" android:valueFrom="1" android:valueTo="0.5"
+ android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="233"
+ android:startOffset="17" android:valueFrom="0.5"
+ android:valueTo="0.5" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="250" android:valueFrom="0.5"
+ android:valueTo="1" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="233"
+ android:startOffset="267" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="500" android:valueFrom="1"
+ android:valueTo="0.5" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="233"
+ android:startOffset="517" android:valueFrom="0.5"
+ android:valueTo="0.5" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="750" android:valueFrom="0.5"
+ android:valueTo="1" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+</set>
diff --git a/core/res/res/anim/ic_bluetooth_transient_animation_1.xml b/core/res/res/anim/ic_bluetooth_transient_animation_1.xml
new file mode 100644
index 0000000..934bd17
--- /dev/null
+++ b/core/res/res/anim/ic_bluetooth_transient_animation_1.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="fillAlpha" android:duration="250"
+ android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="250" android:valueFrom="1"
+ android:valueTo="0.5" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="233"
+ android:startOffset="267" android:valueFrom="0.5"
+ android:valueTo="0.5" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="500" android:valueFrom="0.5"
+ android:valueTo="1" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="233"
+ android:startOffset="517" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="750" android:valueFrom="1"
+ android:valueTo="0.5" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+</set>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/core/res/res/anim/ic_bluetooth_transient_animation_2.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to core/res/res/anim/ic_bluetooth_transient_animation_2.xml
index 8b8258f..7dce34c 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/core/res/res/anim/ic_bluetooth_transient_animation_2.xml
@@ -14,13 +14,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="1000"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+</set>
diff --git a/core/res/res/anim/ic_hotspot_transient_animation_0.xml b/core/res/res/anim/ic_hotspot_transient_animation_0.xml
new file mode 100644
index 0000000..d5a4c52
--- /dev/null
+++ b/core/res/res/anim/ic_hotspot_transient_animation_0.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="0" android:valueFrom="1" android:valueTo="0.5"
+ android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="633"
+ android:startOffset="17" android:valueFrom="0.5"
+ android:valueTo="0.5" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="650" android:valueFrom="0.5"
+ android:valueTo="1" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+</set>
diff --git a/core/res/res/anim/ic_hotspot_transient_animation_1.xml b/core/res/res/anim/ic_hotspot_transient_animation_1.xml
new file mode 100644
index 0000000..36db4b9
--- /dev/null
+++ b/core/res/res/anim/ic_hotspot_transient_animation_1.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="fillAlpha" android:duration="200"
+ android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="200" android:valueFrom="1"
+ android:valueTo="0.5" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="617"
+ android:startOffset="217" android:valueFrom="0.5"
+ android:valueTo="0.5" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="833" android:valueFrom="0.5"
+ android:valueTo="1" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+</set>
diff --git a/core/res/res/anim/ic_hotspot_transient_animation_2.xml b/core/res/res/anim/ic_hotspot_transient_animation_2.xml
new file mode 100644
index 0000000..3d67436
--- /dev/null
+++ b/core/res/res/anim/ic_hotspot_transient_animation_2.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="fillAlpha" android:duration="400"
+ android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="400" android:valueFrom="1"
+ android:valueTo="0.5" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="617"
+ android:startOffset="417" android:valueFrom="0.5"
+ android:valueTo="0.5" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="1033" android:valueFrom="0.5"
+ android:valueTo="1" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator"/>
+</set>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/core/res/res/anim/ic_hotspot_transient_animation_3.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to core/res/res/anim/ic_hotspot_transient_animation_3.xml
index 8b8258f..1495dc9 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/core/res/res/anim/ic_hotspot_transient_animation_3.xml
@@ -15,12 +15,8 @@
~ limitations under the License
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="1250"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+</set>
diff --git a/core/res/res/anim/ic_signal_wifi_transient_animation_0.xml b/core/res/res/anim/ic_signal_wifi_transient_animation_0.xml
new file mode 100644
index 0000000..f71d0ee
--- /dev/null
+++ b/core/res/res/anim/ic_signal_wifi_transient_animation_0.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0"
+ android:startOffset="167" android:valueFrom="1" android:valueTo="0"
+ android:valueType="floatType"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/ic_signal_wifi_transient_animation_1.xml b/core/res/res/anim/ic_signal_wifi_transient_animation_1.xml
new file mode 100644
index 0000000..9af42a1
--- /dev/null
+++ b/core/res/res/anim/ic_signal_wifi_transient_animation_1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="0"
+ android:startOffset="167" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/ic_signal_wifi_transient_animation_2.xml b/core/res/res/anim/ic_signal_wifi_transient_animation_2.xml
new file mode 100644
index 0000000..0e7864a
--- /dev/null
+++ b/core/res/res/anim/ic_signal_wifi_transient_animation_2.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0"
+ android:startOffset="333" android:valueFrom="1" android:valueTo="0"
+ android:valueType="floatType"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/ic_signal_wifi_transient_animation_3.xml b/core/res/res/anim/ic_signal_wifi_transient_animation_3.xml
new file mode 100644
index 0000000..bbec629
--- /dev/null
+++ b/core/res/res/anim/ic_signal_wifi_transient_animation_3.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="0"
+ android:startOffset="333" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/ic_signal_wifi_transient_animation_4.xml b/core/res/res/anim/ic_signal_wifi_transient_animation_4.xml
new file mode 100644
index 0000000..2c921b1
--- /dev/null
+++ b/core/res/res/anim/ic_signal_wifi_transient_animation_4.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0"
+ android:startOffset="500" android:valueFrom="1" android:valueTo="0"
+ android:valueType="floatType"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/ic_signal_wifi_transient_animation_5.xml b/core/res/res/anim/ic_signal_wifi_transient_animation_5.xml
new file mode 100644
index 0000000..51aedc0
--- /dev/null
+++ b/core/res/res/anim/ic_signal_wifi_transient_animation_5.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="0"
+ android:startOffset="500" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/ic_signal_wifi_transient_animation_6.xml b/core/res/res/anim/ic_signal_wifi_transient_animation_6.xml
new file mode 100644
index 0000000..d1da131
--- /dev/null
+++ b/core/res/res/anim/ic_signal_wifi_transient_animation_6.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0"
+ android:startOffset="667" android:valueFrom="1" android:valueTo="0"
+ android:valueType="floatType"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/ic_signal_wifi_transient_animation_7.xml b/core/res/res/anim/ic_signal_wifi_transient_animation_7.xml
new file mode 100644
index 0000000..0b6eb42
--- /dev/null
+++ b/core/res/res/anim/ic_signal_wifi_transient_animation_7.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="0"
+ android:startOffset="667" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/ic_signal_wifi_transient_animation_8.xml b/core/res/res/anim/ic_signal_wifi_transient_animation_8.xml
new file mode 100644
index 0000000..3469d43
--- /dev/null
+++ b/core/res/res/anim/ic_signal_wifi_transient_animation_8.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="833"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/lock_in.xml b/core/res/res/anim/lock_in.xml
old mode 100755
new mode 100644
index e687f9f..c7014e8
--- a/core/res/res/anim/lock_in.xml
+++ b/core/res/res/anim/lock_in.xml
@@ -1,5 +1,4 @@
-<!--
- Copyright (C) 2019 The Android Open Source Project
+<!-- Copyright (C) 2019 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -16,58 +15,116 @@
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
- <vector android:height="32dp" android:width="32dp" android:viewportHeight="32"
+ <vector android:height="42dp" android:width="32dp" android:viewportHeight="42"
android:viewportWidth="32">
<group android:name="_R_G">
- <group android:name="_R_G_L_2_G_N_2_N_1_T_0" android:translateX="16"
- android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
- <group android:name="_R_G_L_2_G_N_2_T_0" android:translateX="-2.25"
- android:translateY="0.75" android:pivotX="2.25" android:pivotY="2.25"
- android:scaleX="0" android:scaleY="0">
- <group android:name="_R_G_L_2_G_T_1" android:translateX="2.25"
- android:translateY="2.373" android:scaleX="0.12346"
- android:scaleY="0.12346">
- <group android:name="_R_G_L_2_G" android:translateY="32">
- <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#ff0000"
- android:fillAlpha="0" android:fillType="nonZero"
- android:trimPathStart="0.14" android:trimPathEnd="0.89"
- android:trimPathOffset="0"
- android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "/>
- <path android:name="_R_G_L_2_G_D_1_P_0"
- android:strokeColor="#000" android:strokeLineCap="round"
- android:strokeLineJoin="round" android:strokeWidth="16"
- android:strokeAlpha="1" android:trimPathStart="0.14"
- android:trimPathEnd="0.89" android:trimPathOffset="0"
- android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "/>
- </group>
+ <group android:name="_R_G_L_2_G" android:translateX="1.6669999999999998"
+ android:translateY="11.992999999999999" android:pivotX="14.333"
+ android:pivotY="13" android:scaleX="0" android:scaleY="0">
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#ffffff"
+ android:strokeLineCap="round" android:strokeLineJoin="round"
+ android:strokeWidth="2" android:strokeAlpha="1"
+ android:pathData=" M22.33 21 C22.33,21 6.33,21 6.33,21 C5.6,21 5,20.4 5,19.67 C5,19.67 5,6.33 5,6.33 C5,5.6 5.6,5 6.33,5 C6.33,5 22.33,5 22.33,5 C23.07,5 23.67,5.6 23.67,6.33 C23.67,6.33 23.67,19.67 23.67,19.67 C23.67,20.4 23.07,21 22.33,21c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="1.6669999999999998"
+ android:translateY="11.992999999999999" android:pivotX="14.333"
+ android:pivotY="13" android:scaleX="0" android:scaleY="0">
+ <group android:name="_R_G_L_1_G" android:translateX="11.583"
+ android:translateY="10.257">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M2.75 0.25 C4.13,0.25 5.25,1.37 5.25,2.75 C5.25,4.13 4.13,5.25 2.75,5.25 C1.37,5.25 0.25,4.13 0.25,2.75 C0.25,1.37 1.37,0.25 2.75,0.25c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="1.6669999999999998"
+ android:translateY="11.992999999999999" android:pivotX="14.333"
+ android:pivotY="13" android:scaleX="0" android:scaleY="0">
+ <group android:name="_R_G_L_0_G_T_1" android:translateX="14.333"
+ android:translateY="3.172">
+ <group android:name="_R_G_L_0_G" android:translateX="-9.667"
+ android:translateY="-9.667">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#ffffff"
+ android:strokeLineCap="round" android:strokeLineJoin="round"
+ android:strokeWidth="2" android:strokeAlpha="1"
+ android:trimPathStart="0.14" android:trimPathEnd="0.89"
+ android:trimPathOffset="0"
+ android:pathData=" M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "/>
</group>
</group>
</group>
- <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="16"
- android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
- <group android:name="_R_G_L_1_G" android:translateX="-8.25"
- android:translateY="-4.25" android:pivotX="8.25" android:pivotY="7.25"
- android:scaleX="0" android:scaleY="0">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
- </group>
- </group>
- <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="16"
- android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
- <group android:name="_R_G_L_0_G" android:translateX="-2.25"
- android:translateY="0.75" android:pivotX="2.25" android:pivotY="2.25"
- android:scaleX="0" android:scaleY="0">
- <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
- </group>
- </group>
</group>
<group android:name="time_group"/>
</vector>
</aapt:attr>
- <target android:name="_R_G_L_2_G_D_0_P_0">
+ <target android:name="_R_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="233"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="233"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="117"
+ android:startOffset="233" android:valueFrom="1.02"
+ android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="117"
+ android:startOffset="233" android:valueFrom="1.02"
+ android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_4_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="233"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="233"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="117"
+ android:startOffset="233" android:valueFrom="1.02"
+ android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="117"
+ android:startOffset="233" android:valueFrom="1.02"
+ android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_0_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="trimPathStart" android:duration="50"
@@ -89,7 +146,7 @@
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_2_G_D_0_P_0">
+ <target android:name="_R_G_L_0_G_D_0_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="trimPathEnd" android:duration="50"
@@ -111,174 +168,48 @@
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_2_G_D_1_P_0">
+ <target android:name="_R_G_L_0_G_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="trimPathStart" android:duration="50"
- android:startOffset="0" android:valueFrom="0.14"
- android:valueTo="0.14" android:valueType="floatType">
+ <objectAnimator android:propertyName="translateY" android:duration="150"
+ android:startOffset="0" android:valueFrom="3.172"
+ android:valueTo="0.34" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="trimPathStart" android:duration="67"
- android:startOffset="50" android:valueFrom="0.14"
- android:valueTo="0" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.23,-0.46 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_2_G_D_1_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="trimPathEnd" android:duration="50"
- android:startOffset="0" android:valueFrom="0.89"
- android:valueTo="0.89" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="trimPathEnd" android:duration="67"
- android:startOffset="50" android:valueFrom="0.89"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_2_G_T_1">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="translateXY" android:duration="150"
- android:startOffset="0" android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 2.25,2.373C 2.25,1.2001604776382402 2.25,-3.49116047763824 2.25,-4.664">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.2,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_2_G_N_2_T_0">
+ <target android:name="_R_G_L_0_G_N_4_T_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="scaleX" android:duration="233"
- android:startOffset="0" android:valueFrom="0"
- android:valueTo="1.0125" android:valueType="floatType">
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleY" android:duration="233"
- android:startOffset="0" android:valueFrom="0"
- android:valueTo="1.0125" android:valueType="floatType">
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleX" android:duration="117"
- android:startOffset="233" android:valueFrom="1.0125"
+ android:startOffset="233" android:valueFrom="1.02"
android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleY" android:duration="117"
- android:startOffset="233" android:valueFrom="1.0125"
+ android:startOffset="233" android:valueFrom="1.02"
android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_2_G_N_2_N_1_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="scaleX" android:duration="0"
- android:startOffset="50" android:valueFrom="0" android:valueTo="1.3"
- android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_1_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="scaleX" android:duration="233"
- android:startOffset="0" android:valueFrom="0"
- android:valueTo="1.025" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.2,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="233"
- android:startOffset="0" android:valueFrom="0"
- android:valueTo="1.025" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.2,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="117"
- android:startOffset="233" android:valueFrom="1.025"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="117"
- android:startOffset="233" android:valueFrom="1.025"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="scaleX" android:duration="233"
- android:startOffset="0" android:valueFrom="0"
- android:valueTo="1.0125" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="233"
- android:startOffset="0" android:valueFrom="0"
- android:valueTo="1.0125" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="117"
- android:startOffset="233" android:valueFrom="1.0125"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="117"
- android:startOffset="233" android:valueFrom="1.0125"
- android:valueTo="1" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
diff --git a/core/res/res/anim/lock_lock.xml b/core/res/res/anim/lock_lock.xml
old mode 100755
new mode 100644
index 8fc4f05..3b8c485
--- a/core/res/res/anim/lock_lock.xml
+++ b/core/res/res/anim/lock_lock.xml
@@ -1,5 +1,4 @@
-<!--
- Copyright (C) 2019 The Android Open Source Project
+<!-- Copyright (C) 2019 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,90 +13,114 @@
limitations under the License.
-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:aapt="http://schemas.android.com/aapt">
+ xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
- <vector android:height="32dp" android:width="32dp" android:viewportHeight="32"
- android:viewportWidth="32">
+ <vector
+ android:width="32dp"
+ android:height="40dp"
+ android:viewportWidth="32"
+ android:viewportHeight="40">
<group android:name="_R_G">
- <group android:name="_R_G_L_2_G_N_1_T_0" android:translateX="16"
- android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
- <group android:name="_R_G_L_2_G_T_1" android:translateX="0"
- android:translateY="3">
- <group android:name="_R_G_L_2_G" android:translateX="-8.25"
- android:translateY="-7.25">
- <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
+ <group
+ android:name="_R_G_L_2_G_T_1"
+ android:translateX="16"
+ android:translateY="23.993">
+ <group
+ android:name="_R_G_L_2_G"
+ android:translateX="-14.333"
+ android:translateY="-13">
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:pathData=" M22.33 21 C22.33,21 6.33,21 6.33,21 C5.6,21 5,20.4 5,19.67 C5,19.67 5,6.33 5,6.33 C5,5.6 5.6,5 6.33,5 C6.33,5 22.33,5 22.33,5 C23.07,5 23.67,5.6 23.67,6.33 C23.67,6.33 23.67,19.67 23.67,19.67 C23.67,20.4 23.07,21 22.33,21c "
+ android:strokeWidth="2"
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff" />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_4_T_1"
+ android:translateX="16"
+ android:translateY="23.993">
+ <group
+ android:name="_R_G_L_1_G_N_4_T_0"
+ android:translateX="-14.333"
+ android:translateY="-13">
+ <group
+ android:name="_R_G_L_1_G"
+ android:pivotX="2.75"
+ android:pivotY="2.75"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="11.583"
+ android:translateY="10.257">
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M2.75 0.25 C4.13,0.25 5.25,1.37 5.25,2.75 C5.25,4.13 4.13,5.25 2.75,5.25 C1.37,5.25 0.25,4.13 0.25,2.75 C0.25,1.37 1.37,0.25 2.75,0.25c " />
</group>
</group>
</group>
- <group android:name="_R_G_L_1_G_N_4_N_1_T_0" android:translateX="16"
- android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
- <group android:name="_R_G_L_1_G_N_4_T_1" android:translateX="0"
- android:translateY="3">
- <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="-8.25"
- android:translateY="-7.25">
- <group android:name="_R_G_L_1_G" android:translateX="6"
- android:translateY="5" android:pivotX="2.25"
- android:pivotY="2.25" android:scaleX="1" android:scaleY="1">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
- </group>
- </group>
- </group>
- </group>
- <group android:name="_R_G_L_0_G_N_4_N_1_T_0" android:translateX="16"
- android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
- <group android:name="_R_G_L_0_G_N_4_T_1" android:translateX="0"
- android:translateY="3">
- <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="-8.25"
- android:translateY="-7.25">
- <group android:name="_R_G_L_0_G" android:translateX="-16.219"
- android:translateY="32.25" android:pivotX="27.965"
- android:pivotY="-32" android:scaleX="0.125"
- android:scaleY="0.125">
- <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ff0000"
- android:fillAlpha="0" android:fillType="nonZero"
- android:pathData=" M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "/>
- <path android:name="_R_G_L_0_G_D_1_P_0"
- android:strokeColor="#000" android:strokeLineCap="round"
- android:strokeLineJoin="round" android:strokeWidth="16"
- android:strokeAlpha="1"
- android:pathData=" M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "/>
- </group>
+ <group
+ android:name="_R_G_L_0_G_N_4_T_1"
+ android:translateX="16"
+ android:translateY="23.993">
+ <group
+ android:name="_R_G_L_0_G_N_4_T_0"
+ android:translateX="-14.333"
+ android:translateY="-13">
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="4.666"
+ android:translateY="-9.327">
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M14.33 14.33 C14.33,14.33 14.32,9.42 14.32,9.42 C14.32,7.4 15.67,5.01 18.65,5 C21.76,4.99 23.07,7.37 23.05,9.47 C23.05,9.47 23.06,9.77 23.06,9.77 "
+ android:strokeWidth="2"
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff" />
</group>
</group>
</group>
</group>
- <group android:name="time_group"/>
+ <group android:name="time_group" />
</vector>
</aapt:attr>
<target android:name="_R_G_L_2_G_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="translateXY" android:duration="400"
- android:startOffset="0" android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 0,3C 0,3.09895833581686 0,3 0,3">
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="23.993"
+ android:valueTo="23.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.667,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateXY" android:duration="67"
- android:startOffset="400" android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 0,3C 0,3.09895833581686 0,3.594 0,3.594">
+ <objectAnimator
+ android:duration="67"
+ android:propertyName="translateY"
+ android:startOffset="400"
+ android:valueFrom="23.993"
+ android:valueTo="25.368"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.58,0 0.549,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateXY" android:duration="83"
- android:startOffset="467" android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 0,3.594C 0,3.594 0,3.09895833581686 0,3">
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="translateY"
+ android:startOffset="467"
+ android:valueFrom="25.368"
+ android:valueTo="23.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.388,0 0.228,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
@@ -106,46 +129,70 @@
<target android:name="_R_G_L_1_G">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="scaleX" android:duration="450"
- android:startOffset="0" android:valueFrom="1" android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator
+ android:duration="450"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="450"
- android:startOffset="0" android:valueFrom="1" android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator
+ android:duration="450"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="67"
- android:startOffset="450" android:valueFrom="1"
- android:valueTo="1.1" android:valueType="floatType">
+ <objectAnimator
+ android:duration="67"
+ android:propertyName="scaleX"
+ android:startOffset="450"
+ android:valueFrom="1"
+ android:valueTo="1.1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="67"
- android:startOffset="450" android:valueFrom="1"
- android:valueTo="1.1" android:valueType="floatType">
+ <objectAnimator
+ android:duration="67"
+ android:propertyName="scaleY"
+ android:startOffset="450"
+ android:valueFrom="1"
+ android:valueTo="1.1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="183"
- android:startOffset="517" android:valueFrom="1.1"
- android:valueTo="1" android:valueType="floatType">
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleX"
+ android:startOffset="517"
+ android:valueFrom="1.1"
+ android:valueTo="1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="183"
- android:startOffset="517" android:valueFrom="1.1"
- android:valueTo="1" android:valueType="floatType">
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleY"
+ android:startOffset="517"
+ android:valueFrom="1.1"
+ android:valueTo="1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
@@ -154,28 +201,37 @@
<target android:name="_R_G_L_1_G_N_4_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="translateXY" android:duration="400"
- android:startOffset="0" android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 0,3C 0,3.09895833581686 0,3 0,3">
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="23.993"
+ android:valueTo="23.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.667,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateXY" android:duration="67"
- android:startOffset="400" android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 0,3C 0,3.09895833581686 0,3.594 0,3.594">
+ <objectAnimator
+ android:duration="67"
+ android:propertyName="translateY"
+ android:startOffset="400"
+ android:valueFrom="23.993"
+ android:valueTo="25.368"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.58,0 0.549,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateXY" android:duration="83"
- android:startOffset="467" android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 0,3.594C 0,3.594 0,3.09895833581686 0,3">
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="translateY"
+ android:startOffset="467"
+ android:valueFrom="25.368"
+ android:valueTo="23.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.388,0 0.228,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
@@ -184,64 +240,26 @@
<target android:name="_R_G_L_0_G_D_0_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="pathData" android:duration="317"
- android:startOffset="0"
- android:valueFrom="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "
- android:valueTo="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 "
- android:valueType="pathType">
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom="M14.33 14.33 C14.33,14.33 14.32,9.42 14.32,9.42 C14.32,7.4 15.67,5.01 18.65,5 C21.76,4.99 23.07,7.37 23.05,9.47 C23.05,9.47 23.06,9.77 23.06,9.77 "
+ android:valueTo="M14.33 14.33 C14.33,14.33 14.29,6.17 14.29,6.17 C14.29,3.59 12.2,1.5 9.63,1.5 C7.05,1.5 4.96,3.59 4.96,6.17 C4.96,6.17 4.96,7.33 4.96,7.33 "
+ android:valueType="pathType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.974,0 0.458,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.692,0 0.298,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="pathData" android:duration="133"
- android:startOffset="317"
- android:valueFrom="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 "
- android:valueTo="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 "
- android:valueType="pathType">
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="pathData"
+ android:startOffset="317"
+ android:valueFrom="M14.33 14.33 C14.33,14.33 14.29,6.17 14.29,6.17 C14.29,3.59 12.2,1.5 9.63,1.5 C7.05,1.5 4.96,3.59 4.96,6.17 C4.96,6.17 4.96,7.33 4.96,7.33 "
+ android:valueTo="M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "
+ android:valueType="pathType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="pathData" android:duration="250"
- android:startOffset="450"
- android:valueFrom="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 "
- android:valueTo="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:valueType="pathType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.414,0 0.647,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_1_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="pathData" android:duration="317"
- android:startOffset="0"
- android:valueFrom="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "
- android:valueTo="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 "
- android:valueType="pathType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.974,0 0.458,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="pathData" android:duration="133"
- android:startOffset="317"
- android:valueFrom="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 "
- android:valueTo="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 "
- android:valueType="pathType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="pathData" android:duration="250"
- android:startOffset="450"
- android:valueFrom="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 "
- android:valueTo="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:valueType="pathType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.414,0 0.647,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.561,0 0.44,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
@@ -250,28 +268,37 @@
<target android:name="_R_G_L_0_G_N_4_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="translateXY" android:duration="400"
- android:startOffset="0" android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 0,3C 0,3.09895833581686 0,3 0,3">
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="23.993"
+ android:valueTo="23.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.667,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateXY" android:duration="67"
- android:startOffset="400" android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 0,3C 0,3.09895833581686 0,3.594 0,3.594">
+ <objectAnimator
+ android:duration="67"
+ android:propertyName="translateY"
+ android:startOffset="400"
+ android:valueFrom="23.993"
+ android:valueTo="25.368"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.58,0 0.549,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateXY" android:duration="83"
- android:startOffset="467" android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 0,3.594C 0,3.594 0,3.09895833581686 0,3">
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="translateY"
+ android:startOffset="467"
+ android:valueFrom="25.368"
+ android:valueTo="23.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.388,0 0.228,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
@@ -280,9 +307,13 @@
<target android:name="time_group">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="translateX" android:duration="717"
- android:startOffset="0" android:valueFrom="0" android:valueTo="1"
- android:valueType="floatType"/>
+ <objectAnimator
+ android:duration="717"
+ android:propertyName="translateX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType" />
</set>
</aapt:attr>
</target>
diff --git a/core/res/res/anim/lock_out.xml b/core/res/res/anim/lock_out.xml
deleted file mode 100755
index 2543d47..0000000
--- a/core/res/res/anim/lock_out.xml
+++ /dev/null
@@ -1,277 +0,0 @@
-<!--
- Copyright (C) 2019 The Android Open 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.
--->
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:aapt="http://schemas.android.com/aapt">
- <aapt:attr name="android:drawable">
- <vector
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <group android:name="_R_G">
- <group android:name="_R_G_L_2_G_N_4_T_0_M">
- <group
- android:name="_R_G_L_2_G_N_4_T_0"
- android:pivotX="8.25"
- android:pivotY="7.25"
- android:scaleX="1"
- android:scaleY="1"
- android:translateX="3.75"
- android:translateY="7.75">
- <group
- android:name="_R_G_L_2_G"
- android:pivotY="-32"
- android:scaleX="0.125"
- android:scaleY="0.125"
- android:translateX="8.25"
- android:translateY="32.267">
- <path
- android:name="_R_G_L_2_G_D_0_P_0"
- android:fillAlpha="0"
- android:fillColor="#ff0000"
- android:fillType="nonZero"
- android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:trimPathStart="0"
- android:trimPathEnd="1"
- android:trimPathOffset="0" />
- <path
- android:name="_R_G_L_2_G_D_1_P_0"
- android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:strokeWidth="16"
- android:strokeAlpha="1"
- android:strokeColor="?attr/textColor"
- android:trimPathStart="0"
- android:trimPathEnd="1"
- android:trimPathOffset="0" />
- </group>
- </group>
- </group>
- <group
- android:name="_R_G_L_1_G"
- android:pivotX="8.25"
- android:pivotY="7.25"
- android:scaleX="1"
- android:scaleY="1"
- android:translateX="3.75"
- android:translateY="7.75">
- <path
- android:name="_R_G_L_1_G_D_0_P_0"
- android:fillAlpha="1"
- android:fillColor="?attr/textColor"
- android:fillType="nonZero"
- android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c " />
- </group>
- <group android:name="_R_G_L_0_G_N_4_T_0_M">
- <group
- android:name="_R_G_L_0_G_N_4_T_0"
- android:pivotX="8.25"
- android:pivotY="7.25"
- android:scaleX="1"
- android:scaleY="1"
- android:translateX="3.75"
- android:translateY="7.75">
- <group
- android:name="_R_G_L_0_G"
- android:translateX="6"
- android:translateY="5">
- <path
- android:name="_R_G_L_0_G_D_0_P_0"
- android:fillAlpha="1"
- android:fillColor="?attr/textColor"
- android:fillType="nonZero"
- android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c " />
- </group>
- </group>
- </group>
- </group>
- <group android:name="time_group" />
- </vector>
- </aapt:attr>
- <target android:name="_R_G_L_2_G_D_1_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="150"
- android:propertyName="strokeAlpha"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_2_G_N_4_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="200"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.09375"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.521,0 0.942,0.896 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="200"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.09375"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.521,0 0.942,0.896 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_2_G_N_4_T_0_M">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="0"
- android:propertyName="scaleY"
- android:startOffset="350"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType" />
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_1_G_D_0_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="150"
- android:propertyName="fillAlpha"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.02"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_1_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="200"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.09375"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.521,0 0.942,0.896 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="200"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.09375"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.521,0 0.942,0.896 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_0_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="83"
- android:propertyName="fillAlpha"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_N_4_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="200"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.09375"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.521,0 0.942,0.896 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="200"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.09375"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.521,0 0.942,0.896 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_N_4_T_0_M">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="0"
- android:propertyName="scaleY"
- android:startOffset="367"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType" />
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="500"
- android:propertyName="translateX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" />
- </set>
- </aapt:attr>
- </target>
-</animated-vector>
\ No newline at end of file
diff --git a/core/res/res/anim/lock_scanning.xml b/core/res/res/anim/lock_scanning.xml
index 8ced02b..db7972f 100644
--- a/core/res/res/anim/lock_scanning.xml
+++ b/core/res/res/anim/lock_scanning.xml
@@ -1,5 +1,4 @@
-<!--
- Copyright (C) 2019 The Android Open Source Project
+<!-- Copyright (C) 2019 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -19,52 +18,36 @@
<vector android:height="42dp" android:width="32dp" android:viewportHeight="42"
android:viewportWidth="32">
<group android:name="_R_G">
- <group android:name="_R_G_L_2_G_N_5_N_1_T_0" android:translateY="5"
- android:pivotX="16" android:pivotY="16" android:scaleX="2"
- android:scaleY="2">
- <group android:name="_R_G_L_2_G_N_5_T_0" android:translateX="7.75"
- android:translateY="10.670000000000002" android:pivotX="8.25"
- android:pivotY="7.25" android:scaleX="0.64" android:scaleY="0.64">
- <group android:name="_R_G_L_2_G" android:translateX="6"
- android:translateY="5" android:pivotX="2.25" android:pivotY="2.25"
- android:scaleX="1" android:scaleY="1">
- <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
- </group>
+ <group android:name="_R_G_L_2_G" android:translateX="1.6669999999999998"
+ android:translateY="11.992999999999999" android:pivotX="14.333"
+ android:pivotY="13" android:scaleX="1" android:scaleY="1">
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#ffffff"
+ android:strokeLineCap="round" android:strokeLineJoin="round"
+ android:strokeWidth="2" android:strokeAlpha="1"
+ android:pathData=" M22.33 21 C22.33,21 6.33,21 6.33,21 C5.6,21 5,20.4 5,19.67 C5,19.67 5,6.33 5,6.33 C5,5.6 5.6,5 6.33,5 C6.33,5 22.33,5 22.33,5 C23.07,5 23.67,5.6 23.67,6.33 C23.67,6.33 23.67,19.67 23.67,19.67 C23.67,20.4 23.07,21 22.33,21c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_N_7_T_0" android:translateX="1.6669999999999998"
+ android:translateY="11.992999999999999" android:pivotX="14.333"
+ android:pivotY="13" android:scaleX="1" android:scaleY="1">
+ <group android:name="_R_G_L_1_G" android:translateX="11.583"
+ android:translateY="10.257" android:pivotX="2.75" android:pivotY="2.75"
+ android:scaleX="1" android:scaleY="1">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M2.75 0.25 C4.13,0.25 5.25,1.37 5.25,2.75 C5.25,4.13 4.13,5.25 2.75,5.25 C1.37,5.25 0.25,4.13 0.25,2.75 C0.25,1.37 1.37,0.25 2.75,0.25c "/>
</group>
</group>
- <group android:name="_R_G_L_1_G_N_5_N_1_T_0" android:translateY="5"
- android:pivotX="16" android:pivotY="16" android:scaleX="2"
- android:scaleY="2">
- <group android:name="_R_G_L_1_G_N_5_T_0" android:translateX="7.75"
- android:translateY="10.670000000000002" android:pivotX="8.25"
- android:pivotY="7.25" android:scaleX="0.64" android:scaleY="0.64">
- <group android:name="_R_G_L_1_G_T_1" android:translateX="8.25"
- android:translateY="1.121" android:scaleX="0.125"
- android:scaleY="0.125">
- <group android:name="_R_G_L_1_G" android:translateY="25.029">
- <path android:name="_R_G_L_1_G_D_0_P_0"
- android:strokeColor="#000" android:strokeLineCap="round"
- android:strokeLineJoin="round" android:strokeWidth="16"
- android:strokeAlpha="1"
- android:pathData=" M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "/>
- </group>
- </group>
- </group>
- </group>
- <group android:name="_R_G_L_0_G_N_5_N_1_T_0" android:translateY="5"
- android:pivotX="16" android:pivotY="16" android:scaleX="2"
- android:scaleY="2">
- <group android:name="_R_G_L_0_G_N_5_T_0" android:translateX="7.75"
- android:translateY="10.670000000000002" android:pivotX="8.25"
- android:pivotY="7.25" android:scaleX="0.64" android:scaleY="0.64">
- <group android:name="_R_G_L_0_G" android:translateY="0.04699999999999971"
- android:pivotX="8.25" android:pivotY="7.25" android:scaleX="1.01562"
- android:scaleY="1.01563">
- <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
+ <group android:name="_R_G_L_0_G_N_7_T_0" android:translateX="1.6669999999999998"
+ android:translateY="11.992999999999999" android:pivotX="14.333"
+ android:pivotY="13" android:scaleX="1" android:scaleY="1">
+ <group android:name="_R_G_L_0_G_T_1" android:translateX="14.333"
+ android:translateY="0.34">
+ <group android:name="_R_G_L_0_G" android:translateX="-9.667"
+ android:translateY="-9.667">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#ffffff"
+ android:strokeLineCap="round" android:strokeLineJoin="round"
+ android:strokeWidth="2" android:strokeAlpha="1"
+ android:pathData=" M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "/>
</group>
</group>
</group>
@@ -75,6 +58,68 @@
<target android:name="_R_G_L_2_G">
<aapt:attr name="android:animation">
<set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="83"
+ android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="83"
+ android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="83"
+ android:startOffset="83" android:valueFrom="1"
+ android:valueTo="0.96" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="83"
+ android:startOffset="83" android:valueFrom="1"
+ android:valueTo="0.96" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="183"
+ android:startOffset="167" android:valueFrom="0.96"
+ android:valueTo="1.28" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="183"
+ android:startOffset="167" android:valueFrom="0.96"
+ android:valueTo="1.28" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="250"
+ android:startOffset="350" android:valueFrom="1.28"
+ android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="250"
+ android:startOffset="350" android:valueFrom="1.28"
+ android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
<objectAnimator android:propertyName="scaleX" android:duration="150"
android:startOffset="0" android:valueFrom="1" android:valueTo="1"
android:valueType="floatType">
@@ -120,61 +165,61 @@
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_2_G_N_5_T_0">
+ <target android:name="_R_G_L_1_G_N_7_T_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="scaleX" android:duration="83"
- android:startOffset="0" android:valueFrom="0.64"
- android:valueTo="0.64" android:valueType="floatType">
+ android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleY" android:duration="83"
- android:startOffset="0" android:valueFrom="0.64"
- android:valueTo="0.64" android:valueType="floatType">
+ android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleX" android:duration="83"
- android:startOffset="83" android:valueFrom="0.64"
- android:valueTo="0.62" android:valueType="floatType">
+ android:startOffset="83" android:valueFrom="1"
+ android:valueTo="0.96" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleY" android:duration="83"
- android:startOffset="83" android:valueFrom="0.64"
- android:valueTo="0.62" android:valueType="floatType">
+ android:startOffset="83" android:valueFrom="1"
+ android:valueTo="0.96" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleX" android:duration="183"
- android:startOffset="167" android:valueFrom="0.62"
- android:valueTo="0.8" android:valueType="floatType">
+ android:startOffset="167" android:valueFrom="0.96"
+ android:valueTo="1.28" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleY" android:duration="183"
- android:startOffset="167" android:valueFrom="0.62"
- android:valueTo="0.8" android:valueType="floatType">
+ android:startOffset="167" android:valueFrom="0.96"
+ android:valueTo="1.28" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleX" android:duration="250"
- android:startOffset="350" android:valueFrom="0.8"
- android:valueTo="0.64" android:valueType="floatType">
+ android:startOffset="350" android:valueFrom="1.28"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleY" android:duration="250"
- android:startOffset="350" android:valueFrom="0.8"
- android:valueTo="0.64" android:valueType="floatType">
+ android:startOffset="350" android:valueFrom="1.28"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
@@ -182,13 +227,13 @@
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_1_G_D_0_P_0">
+ <target android:name="_R_G_L_0_G_D_0_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="pathData" android:duration="83"
android:startOffset="0"
- android:valueFrom="M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "
- android:valueTo="M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "
+ android:valueFrom="M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "
+ android:valueTo="M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "
android:valueType="pathType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
@@ -196,8 +241,8 @@
</objectAnimator>
<objectAnimator android:propertyName="pathData" android:duration="150"
android:startOffset="83"
- android:valueFrom="M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "
- android:valueTo="M-28.02 -43.42 C-28.02,-43.42 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.76,-43.67 27.76,-43.67 "
+ android:valueFrom="M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "
+ android:valueTo="M14.31 10.37 C14.31,10.37 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 4.97,10.37 4.97,10.37 "
android:valueType="pathType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
@@ -205,8 +250,8 @@
</objectAnimator>
<objectAnimator android:propertyName="pathData" android:duration="117"
android:startOffset="233"
- android:valueFrom="M-28.02 -43.42 C-28.02,-43.42 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.76,-43.67 27.76,-43.67 "
- android:valueTo="M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "
+ android:valueFrom="M14.31 10.37 C14.31,10.37 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 4.97,10.37 4.97,10.37 "
+ android:valueTo="M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "
android:valueType="pathType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
@@ -215,150 +260,88 @@
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_1_G_T_1">
+ <target android:name="_R_G_L_0_G_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="translateY" android:duration="83"
- android:startOffset="0" android:valueFrom="1.121"
- android:valueTo="1.121" android:valueType="floatType">
+ android:startOffset="0" android:valueFrom="0.34"
+ android:valueTo="0.34" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.384,0 0.536,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="translateY" android:duration="150"
- android:startOffset="83" android:valueFrom="1.121"
- android:valueTo="3.749" android:valueType="floatType">
+ android:startOffset="83" android:valueFrom="0.34"
+ android:valueTo="4.364" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.384,0 0.536,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="translateY" android:duration="117"
- android:startOffset="233" android:valueFrom="3.749"
- android:valueTo="1.121" android:valueType="floatType">
+ android:startOffset="233" android:valueFrom="4.364"
+ android:valueTo="0.34" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.442,0 0.594,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_1_G_N_5_T_0">
+ <target android:name="_R_G_L_0_G_N_7_T_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="scaleX" android:duration="83"
- android:startOffset="0" android:valueFrom="0.64"
- android:valueTo="0.64" android:valueType="floatType">
+ android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleY" android:duration="83"
- android:startOffset="0" android:valueFrom="0.64"
- android:valueTo="0.64" android:valueType="floatType">
+ android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleX" android:duration="83"
- android:startOffset="83" android:valueFrom="0.64"
- android:valueTo="0.62" android:valueType="floatType">
+ android:startOffset="83" android:valueFrom="1"
+ android:valueTo="0.96" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleY" android:duration="83"
- android:startOffset="83" android:valueFrom="0.64"
- android:valueTo="0.62" android:valueType="floatType">
+ android:startOffset="83" android:valueFrom="1"
+ android:valueTo="0.96" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleX" android:duration="183"
- android:startOffset="167" android:valueFrom="0.62"
- android:valueTo="0.8" android:valueType="floatType">
+ android:startOffset="167" android:valueFrom="0.96"
+ android:valueTo="1.28" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleY" android:duration="183"
- android:startOffset="167" android:valueFrom="0.62"
- android:valueTo="0.8" android:valueType="floatType">
+ android:startOffset="167" android:valueFrom="0.96"
+ android:valueTo="1.28" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleX" android:duration="250"
- android:startOffset="350" android:valueFrom="0.8"
- android:valueTo="0.64" android:valueType="floatType">
+ android:startOffset="350" android:valueFrom="1.28"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="scaleY" android:duration="250"
- android:startOffset="350" android:valueFrom="0.8"
- android:valueTo="0.64" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_N_5_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="scaleX" android:duration="83"
- android:startOffset="0" android:valueFrom="0.64"
- android:valueTo="0.64" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="83"
- android:startOffset="0" android:valueFrom="0.64"
- android:valueTo="0.64" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="83"
- android:startOffset="83" android:valueFrom="0.64"
- android:valueTo="0.62" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="83"
- android:startOffset="83" android:valueFrom="0.64"
- android:valueTo="0.62" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="183"
- android:startOffset="167" android:valueFrom="0.62"
- android:valueTo="0.8" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="183"
- android:startOffset="167" android:valueFrom="0.62"
- android:valueTo="0.8" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="250"
- android:startOffset="350" android:valueFrom="0.8"
- android:valueTo="0.64" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="250"
- android:startOffset="350" android:valueFrom="0.8"
- android:valueTo="0.64" android:valueType="floatType">
+ android:startOffset="350" android:valueFrom="1.28"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
@@ -369,7 +352,7 @@
<target android:name="time_group">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="translateX" android:duration="1000"
+ <objectAnimator android:propertyName="translateX" android:duration="717"
android:startOffset="0" android:valueFrom="0" android:valueTo="1"
android:valueType="floatType"/>
</set>
diff --git a/core/res/res/anim/lock_to_error.xml b/core/res/res/anim/lock_to_error.xml
old mode 100755
new mode 100644
index afe2290..e356f26
--- a/core/res/res/anim/lock_to_error.xml
+++ b/core/res/res/anim/lock_to_error.xml
@@ -1,5 +1,4 @@
-<!--
- Copyright (C) 2019 The Android Open Source Project
+<!-- Copyright (C) 2019 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -19,161 +18,157 @@
<vector android:height="32dp" android:width="32dp" android:viewportHeight="32"
android:viewportWidth="32">
<group android:name="_R_G">
- <group android:name="_R_G_L_2_G_N_2_T_0" android:translateX="7.75"
- android:translateY="12.649999999999999" android:pivotX="8.25"
- android:pivotY="7.25" android:rotation="0" android:scaleX="1.3"
- android:scaleY="1.3">
- <group android:name="_R_G_L_2_G" android:translateX="6"
- android:translateY="4.954" android:pivotX="2.25" android:pivotY="2.25"
- android:scaleX="0.98462" android:scaleY="0.98462">
- <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000"
+ <group android:name="_R_G_L_2_G" android:translateX="1.6669999999999998"
+ android:translateY="6.9929999999999986" android:pivotX="14.333"
+ android:pivotY="13" android:rotation="0">
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#ffffff"
+ android:strokeLineCap="round" android:strokeLineJoin="round"
+ android:strokeWidth="2" android:strokeAlpha="1"
+ android:pathData=" M22.33 21 C22.33,21 6.33,21 6.33,21 C5.6,21 5,20.4 5,19.67 C5,19.67 5,6.33 5,6.33 C5,5.6 5.6,5 6.33,5 C6.33,5 22.33,5 22.33,5 C23.07,5 23.67,5.6 23.67,6.33 C23.67,6.33 23.67,19.67 23.67,19.67 C23.67,20.4 23.07,21 22.33,21c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="1.6669999999999998"
+ android:translateY="6.9929999999999986" android:pivotX="14.333"
+ android:pivotY="13" android:rotation="0">
+ <group android:name="_R_G_L_1_G" android:translateX="11.583"
+ android:translateY="10.257">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff"
android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
+ android:pathData=" M2.75 0.25 C4.13,0.25 5.25,1.37 5.25,2.75 C5.25,4.13 4.13,5.25 2.75,5.25 C1.37,5.25 0.25,4.13 0.25,2.75 C0.25,1.37 1.37,0.25 2.75,0.25c "/>
</group>
</group>
- <group android:name="_R_G_L_1_G_N_2_T_0" android:translateX="7.75"
- android:translateY="12.649999999999999" android:pivotX="8.25"
- android:pivotY="7.25" android:rotation="0" android:scaleX="1.3"
- android:scaleY="1.3">
- <group android:name="_R_G_L_1_G" android:translateX="-16.273"
- android:translateY="32.312" android:pivotX="27.965" android:pivotY="-32"
- android:scaleX="0.12308" android:scaleY="0.12308">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#000"
+ <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="1.6669999999999998"
+ android:translateY="6.9929999999999986" android:pivotX="14.333"
+ android:pivotY="13" android:rotation="0">
+ <group android:name="_R_G_L_0_G" android:translateX="4.666"
+ android:translateY="-9.327">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#ffffff"
android:strokeLineCap="round" android:strokeLineJoin="round"
- android:strokeWidth="16" android:strokeAlpha="1"
- android:pathData=" M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "/>
+ android:strokeWidth="2" android:strokeAlpha="1"
+ android:pathData=" M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "/>
</group>
</group>
- <group android:name="_R_G_L_0_G" android:translateX="7.75"
- android:translateY="12.649999999999999" android:pivotX="8.25"
- android:pivotY="7.25" android:rotation="0" android:scaleX="1.3"
- android:scaleY="1.3">
- <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
- </group>
</group>
<group android:name="time_group"/>
</vector>
</aapt:attr>
- <target android:name="_R_G_L_2_G_N_2_T_0">
+ <target android:name="_R_G_L_2_G">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="rotation" android:duration="133"
android:startOffset="0" android:valueFrom="0" android:valueTo="0"
android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.465,0 0.558,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="rotation" android:duration="120"
+ <objectAnimator android:propertyName="rotation" android:duration="117"
android:startOffset="133" android:valueFrom="0"
android:valueTo="-10" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.465,0 0.558,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="rotation" android:duration="97"
- android:startOffset="253" android:valueFrom="-10"
+ <objectAnimator android:propertyName="rotation" android:duration="100"
+ android:startOffset="250" android:valueFrom="-10"
android:valueTo="10" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.51,0 0.531,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="rotation" android:duration="100"
android:startOffset="350" android:valueFrom="10"
android:valueTo="-5" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.469,0 0.599,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="rotation" android:duration="167"
android:startOffset="450" android:valueFrom="-5" android:valueTo="0"
android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.384,0 0.565,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_1_G_N_2_T_0">
+ <target android:name="_R_G_L_1_G_N_4_T_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="rotation" android:duration="133"
android:startOffset="0" android:valueFrom="0" android:valueTo="0"
android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.465,0 0.558,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="rotation" android:duration="120"
+ <objectAnimator android:propertyName="rotation" android:duration="117"
android:startOffset="133" android:valueFrom="0"
android:valueTo="-10" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.465,0 0.558,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="rotation" android:duration="97"
- android:startOffset="253" android:valueFrom="-10"
+ <objectAnimator android:propertyName="rotation" android:duration="100"
+ android:startOffset="250" android:valueFrom="-10"
android:valueTo="10" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.51,0 0.531,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="rotation" android:duration="100"
android:startOffset="350" android:valueFrom="10"
android:valueTo="-5" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.469,0 0.599,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="rotation" android:duration="167"
android:startOffset="450" android:valueFrom="-5" android:valueTo="0"
android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.384,0 0.565,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_0_G">
+ <target android:name="_R_G_L_0_G_N_4_T_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="rotation" android:duration="133"
android:startOffset="0" android:valueFrom="0" android:valueTo="0"
android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.465,0 0.558,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="rotation" android:duration="120"
+ <objectAnimator android:propertyName="rotation" android:duration="117"
android:startOffset="133" android:valueFrom="0"
android:valueTo="-10" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.465,0 0.558,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="rotation" android:duration="97"
- android:startOffset="253" android:valueFrom="-10"
+ <objectAnimator android:propertyName="rotation" android:duration="100"
+ android:startOffset="250" android:valueFrom="-10"
android:valueTo="10" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.51,0 0.531,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="rotation" android:duration="100"
android:startOffset="350" android:valueFrom="10"
android:valueTo="-5" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.469,0 0.599,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
<objectAnimator android:propertyName="rotation" android:duration="167"
android:startOffset="450" android:valueFrom="-5" android:valueTo="0"
android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.384,0 0.565,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
@@ -182,7 +177,7 @@
<target android:name="time_group">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="translateX" android:duration="1000"
+ <objectAnimator android:propertyName="translateX" android:duration="717"
android:startOffset="0" android:valueFrom="0" android:valueTo="1"
android:valueType="floatType"/>
</set>
diff --git a/core/res/res/anim/lock_unlock.xml b/core/res/res/anim/lock_unlock.xml
old mode 100755
new mode 100644
index c8b2608..91d4432
--- a/core/res/res/anim/lock_unlock.xml
+++ b/core/res/res/anim/lock_unlock.xml
@@ -1,5 +1,4 @@
-<!--
- Copyright (C) 2019 The Android Open Source Project
+<!-- Copyright (C) 2019 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,85 +13,114 @@
limitations under the License.
-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:aapt="http://schemas.android.com/aapt">
+ xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
- <vector android:height="40dp" android:width="32dp" android:viewportHeight="40"
- android:viewportWidth="32">
+ <vector
+ android:width="32dp"
+ android:height="42dp"
+ android:viewportWidth="32"
+ android:viewportHeight="42">
<group android:name="_R_G">
- <group android:name="_R_G_L_2_G_N_1_T_0" android:translateX="16"
- android:translateY="20" android:scaleX="1.3" android:scaleY="1.3">
- <group android:name="_R_G_L_2_G_T_1" android:translateY="3">
- <group android:name="_R_G_L_2_G" android:translateX="-8.25"
- android:translateY="-7.25">
- <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
+ <group
+ android:name="_R_G_L_2_G_T_1"
+ android:translateX="16"
+ android:translateY="24.993">
+ <group
+ android:name="_R_G_L_2_G"
+ android:translateX="-14.333"
+ android:translateY="-13">
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:pathData=" M22.33 21 C22.33,21 6.33,21 6.33,21 C5.6,21 5,20.4 5,19.67 C5,19.67 5,6.33 5,6.33 C5,5.6 5.6,5 6.33,5 C6.33,5 22.33,5 22.33,5 C23.07,5 23.67,5.6 23.67,6.33 C23.67,6.33 23.67,19.67 23.67,19.67 C23.67,20.4 23.07,21 22.33,21c "
+ android:strokeWidth="2"
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff" />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_4_T_1"
+ android:translateX="16"
+ android:translateY="24.993">
+ <group
+ android:name="_R_G_L_1_G_N_4_T_0"
+ android:translateX="-14.333"
+ android:translateY="-13">
+ <group
+ android:name="_R_G_L_1_G"
+ android:pivotX="2.75"
+ android:pivotY="2.75"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="11.583"
+ android:translateY="10.257">
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M2.75 0.25 C4.13,0.25 5.25,1.37 5.25,2.75 C5.25,4.13 4.13,5.25 2.75,5.25 C1.37,5.25 0.25,4.13 0.25,2.75 C0.25,1.37 1.37,0.25 2.75,0.25c " />
</group>
</group>
</group>
- <group android:name="_R_G_L_1_G_N_4_N_1_T_0" android:translateX="16"
- android:translateY="20" android:scaleX="1.3" android:scaleY="1.3">
- <group android:name="_R_G_L_1_G_N_4_T_1" android:translateY="3">
- <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="-8.25"
- android:translateY="-7.25">
- <group android:name="_R_G_L_1_G" android:translateX="6"
- android:translateY="5" android:pivotX="2.25"
- android:pivotY="2.25" android:scaleX="1" android:scaleY="1">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
- </group>
- </group>
- </group>
- </group>
- <group android:name="_R_G_L_0_G_N_4_N_1_T_0" android:translateX="16"
- android:translateY="20" android:scaleX="1.3" android:scaleY="1.3">
- <group android:name="_R_G_L_0_G_N_4_T_1" android:translateY="3">
- <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="-8.25"
- android:translateY="-7.25">
- <group android:name="_R_G_L_0_G" android:translateX="-16.219"
- android:translateY="32.25" android:pivotX="27.965"
- android:pivotY="-32" android:scaleX="0.125"
- android:scaleY="0.125">
- <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ff0000"
- android:fillAlpha="0" android:fillType="nonZero"
- android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "/>
- <path android:name="_R_G_L_0_G_D_1_P_0"
- android:strokeColor="#000" android:strokeLineCap="round"
- android:strokeLineJoin="round" android:strokeWidth="16"
- android:strokeAlpha="1"
- android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "/>
- </group>
+ <group
+ android:name="_R_G_L_0_G_N_4_T_1"
+ android:translateX="16"
+ android:translateY="24.993">
+ <group
+ android:name="_R_G_L_0_G_N_4_T_0"
+ android:translateX="-14.333"
+ android:translateY="-13">
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="4.666"
+ android:translateY="-9.327">
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "
+ android:strokeWidth="2"
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff" />
</group>
</group>
</group>
</group>
- <group android:name="time_group"/>
+ <group android:name="time_group" />
</vector>
</aapt:attr>
<target android:name="_R_G_L_2_G_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="translateY" android:duration="133"
- android:startOffset="0" android:valueFrom="3"
- android:valueTo="1.625" android:valueType="floatType">
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="24.993"
+ android:valueTo="22.493"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.075,0.167 0.622,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.378,0 0.622,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateY" android:duration="133"
- android:startOffset="133" android:valueFrom="1.625"
- android:valueTo="3.699" android:valueType="floatType">
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="133"
+ android:valueFrom="22.493"
+ android:valueTo="25.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.352,0 0.717,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.41,0 0.616,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateY" android:duration="100"
- android:startOffset="267" android:valueFrom="3.699"
- android:valueTo="3" android:valueType="floatType">
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="translateY"
+ android:startOffset="267"
+ android:valueFrom="25.993"
+ android:valueTo="24.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.356,0 0.527,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.427,0 0.508,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
@@ -101,32 +129,48 @@
<target android:name="_R_G_L_1_G">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="scaleX" android:duration="100"
- android:startOffset="0" android:valueFrom="1" android:valueTo="0.85"
- android:valueType="floatType">
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.8200000000000001"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.418,0 0.565,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="100"
- android:startOffset="0" android:valueFrom="1" android:valueTo="0.85"
- android:valueType="floatType">
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.8200000000000001"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.418,0 0.565,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="283"
- android:startOffset="100" android:valueFrom="0.85"
- android:valueTo="1" android:valueType="floatType">
+ <objectAnimator
+ android:duration="283"
+ android:propertyName="scaleX"
+ android:startOffset="100"
+ android:valueFrom="0.8200000000000001"
+ android:valueTo="1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.535,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="283"
- android:startOffset="100" android:valueFrom="0.85"
- android:valueTo="1" android:valueType="floatType">
+ <objectAnimator
+ android:duration="283"
+ android:propertyName="scaleY"
+ android:startOffset="100"
+ android:valueFrom="0.8200000000000001"
+ android:valueTo="1"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.535,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
@@ -135,26 +179,37 @@
<target android:name="_R_G_L_1_G_N_4_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="translateY" android:duration="133"
- android:startOffset="0" android:valueFrom="3"
- android:valueTo="1.625" android:valueType="floatType">
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="24.993"
+ android:valueTo="22.493"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.075,0.167 0.622,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.378,0 0.622,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateY" android:duration="133"
- android:startOffset="133" android:valueFrom="1.625"
- android:valueTo="3.699" android:valueType="floatType">
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="133"
+ android:valueFrom="22.493"
+ android:valueTo="25.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.352,0 0.717,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.41,0 0.616,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateY" android:duration="100"
- android:startOffset="267" android:valueFrom="3.699"
- android:valueTo="3" android:valueType="floatType">
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="translateY"
+ android:startOffset="267"
+ android:valueFrom="25.993"
+ android:valueTo="24.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.356,0 0.527,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.427,0 0.508,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
@@ -163,46 +218,26 @@
<target android:name="_R_G_L_0_G_D_0_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="pathData" android:duration="67"
- android:startOffset="0"
- android:valueFrom="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:valueTo="M-27.97 -59.3 C-27.97,-59.3 -28,-64.5 -27.97,-66.23 C-27.92,-68.37 -23.5,-90.63 -0.75,-90.57 C22.77,-90.51 27.75,-70.12 27.72,-69.02 C27.55,-63.63 27.97,-25.67 27.97,-25.67 "
- android:valueType="pathType">
+ <objectAnimator
+ android:duration="67"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom="M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "
+ android:valueTo="M14.33 14.33 C14.33,14.33 14.29,6.17 14.29,6.17 C14.29,3.59 12.2,1.5 9.63,1.5 C7.05,1.5 4.96,3.59 4.96,6.17 C4.96,6.17 4.96,7.33 4.96,7.33 "
+ android:valueType="pathType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.353,0 0.2,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.56,0 0.439,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="pathData" android:duration="333"
- android:startOffset="67"
- android:valueFrom="M-27.97 -59.3 C-27.97,-59.3 -28,-64.5 -27.97,-66.23 C-27.92,-68.37 -23.5,-90.63 -0.75,-90.57 C22.77,-90.51 27.75,-70.12 27.72,-69.02 C27.55,-63.63 27.97,-25.67 27.97,-25.67 "
- android:valueTo="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "
- android:valueType="pathType">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="pathData"
+ android:startOffset="67"
+ android:valueFrom="M14.33 14.33 C14.33,14.33 14.29,6.17 14.29,6.17 C14.29,3.59 12.2,1.5 9.63,1.5 C7.05,1.5 4.96,3.59 4.96,6.17 C4.96,6.17 4.96,7.33 4.96,7.33 "
+ android:valueTo="M14.33 14.33 C14.33,14.33 14.32,9.42 14.32,9.42 C14.32,7.4 15.67,5.01 18.65,5 C21.76,4.99 23.07,7.37 23.05,9.47 C23.05,9.47 23.06,9.77 23.06,9.77 "
+ android:valueType="pathType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.542,0 0.026,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_1_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:propertyName="pathData" android:duration="67"
- android:startOffset="0"
- android:valueFrom="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:valueTo="M-27.97 -59.3 C-27.97,-59.3 -28,-64.5 -27.97,-66.23 C-27.92,-68.37 -23.5,-90.63 -0.75,-90.57 C22.77,-90.51 27.75,-70.12 27.72,-69.02 C27.55,-63.63 27.97,-25.67 27.97,-25.67 "
- android:valueType="pathType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.353,0 0.2,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="pathData" android:duration="333"
- android:startOffset="67"
- android:valueFrom="M-27.97 -59.3 C-27.97,-59.3 -28,-64.5 -27.97,-66.23 C-27.92,-68.37 -23.5,-90.63 -0.75,-90.57 C22.77,-90.51 27.75,-70.12 27.72,-69.02 C27.55,-63.63 27.97,-25.67 27.97,-25.67 "
- android:valueTo="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "
- android:valueType="pathType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.542,0 0.026,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.702,0 0.308,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
@@ -211,26 +246,37 @@
<target android:name="_R_G_L_0_G_N_4_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="translateY" android:duration="133"
- android:startOffset="0" android:valueFrom="3"
- android:valueTo="1.625" android:valueType="floatType">
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="24.993"
+ android:valueTo="22.493"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator
- android:pathData="M 0.0,0.0 c0.075,0.167 0.622,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.378,0 0.622,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateY" android:duration="133"
- android:startOffset="133" android:valueFrom="1.625"
- android:valueTo="3.699" android:valueType="floatType">
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="133"
+ android:valueFrom="22.493"
+ android:valueTo="25.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.352,0 0.717,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.41,0 0.616,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
- <objectAnimator android:propertyName="translateY" android:duration="100"
- android:startOffset="267" android:valueFrom="3.699"
- android:valueTo="3" android:valueType="floatType">
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="translateY"
+ android:startOffset="267"
+ android:valueFrom="25.993"
+ android:valueTo="24.993"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.356,0 0.527,1 1.0,1.0"/>
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.427,0 0.508,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
@@ -239,9 +285,13 @@
<target android:name="time_group">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="translateX" android:duration="717"
- android:startOffset="0" android:valueFrom="0" android:valueTo="1"
- android:valueType="floatType"/>
+ <objectAnimator
+ android:duration="717"
+ android:propertyName="translateX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType" />
</set>
</aapt:attr>
</target>
diff --git a/core/res/res/anim/resolver_close_anim.xml b/core/res/res/anim/resolver_close_anim.xml
new file mode 100644
index 0000000..18a25e9
--- /dev/null
+++ b/core/res/res/anim/resolver_close_anim.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@anim/accelerate_interpolator"
+ android:zAdjustment="top">
+
+ <translate xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fromYDelta="0"
+ android:toYDelta="100%"
+ android:duration="@android:integer/config_shortAnimTime" />
+</set>
diff --git a/core/res/res/anim/resolver_launch_anim.xml b/core/res/res/anim/resolver_launch_anim.xml
new file mode 100644
index 0000000..ebb3701
--- /dev/null
+++ b/core/res/res/anim/resolver_launch_anim.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+
+<!-- Animation for when a dock window at the bottom of the screen is entering. -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@anim/accelerate_decelerate_interpolator"
+ android:zAdjustment="top">
+
+ <translate android:fromYDelta="100%"
+ android:toYDelta="0"
+ android:startOffset="@android:integer/config_shortAnimTime"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_bluetooth_transient_animation.xml b/core/res/res/drawable/ic_bluetooth_transient_animation.xml
new file mode 100644
index 0000000..61b0f1a
--- /dev/null
+++ b/core/res/res/drawable/ic_bluetooth_transient_animation.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_bluetooth_transient_animation_drawable">
+ <target android:name="_R_G_L_0_G_D_1_P_0"
+ android:animation="@anim/ic_bluetooth_transient_animation_0"/>
+ <target android:name="_R_G_L_0_G_D_2_P_0"
+ android:animation="@anim/ic_bluetooth_transient_animation_1"/>
+ <target android:name="time_group" android:animation="@anim/ic_bluetooth_transient_animation_2"/>
+</animated-vector>
diff --git a/core/res/res/drawable/ic_bluetooth_transient_animation_drawable.xml b/core/res/res/drawable/ic_bluetooth_transient_animation_drawable.xml
new file mode 100644
index 0000000..a520fea
--- /dev/null
+++ b/core/res/res/drawable/ic_bluetooth_transient_animation_drawable.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp"
+ android:width="24dp" android:viewportHeight="24"
+ android:viewportWidth="24">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12"
+ android:translateY="12">
+ <group android:name="_R_G_L_0_G" android:translateX="-12"
+ android:translateY="-12">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M17.71 7.71 C17.71,7.71 12,2 12,2 C12,2 11,2 11,2 C11,2 11,9.59 11,9.59 C11,9.59 6.41,5 6.41,5 C6.41,5 5,6.41 5,6.41 C5,6.41 10.59,12 10.59,12 C10.59,12 5,17.59 5,17.59 C5,17.59 6.41,19 6.41,19 C6.41,19 11,14.41 11,14.41 C11,14.41 11,22 11,22 C11,22 12,22 12,22 C12,22 17.71,16.29 17.71,16.29 C17.71,16.29 13.41,12 13.41,12 C13.41,12 17.71,7.71 17.71,7.71c M13 5.83 C13,5.83 14.88,7.71 14.88,7.71 C14.88,7.71 13,9.59 13,9.59 C13,9.59 13,5.83 13,5.83c M14.88 16.29 C14.88,16.29 13,18.17 13,18.17 C13,18.17 13,14.41 13,14.41 C13,14.41 14.88,16.29 14.88,16.29c "/>
+ <path android:name="_R_G_L_0_G_D_1_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M5 10.5 C5.83,10.5 6.5,11.17 6.5,12 C6.5,12.83 5.83,13.5 5,13.5 C4.17,13.5 3.5,12.83 3.5,12 C3.5,11.17 4.17,10.5 5,10.5c "/>
+ <path android:name="_R_G_L_0_G_D_2_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M19 10.5 C19.83,10.5 20.5,11.17 20.5,12 C20.5,12.83 19.83,13.5 19,13.5 C18.17,13.5 17.5,12.83 17.5,12 C17.5,11.17 18.17,10.5 19,10.5c "/>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_corp_badge.xml b/core/res/res/drawable/ic_corp_badge.xml
index 5ab5045..6a7ac4a 100644
--- a/core/res/res/drawable/ic_corp_badge.xml
+++ b/core/res/res/drawable/ic_corp_badge.xml
@@ -17,9 +17,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
+ android:tint="@*android:color/accent_device_default_light"
android:viewportWidth="24"
android:viewportHeight="24">
<path
- android:fillColor="@*android:color/accent_device_default_light"
- android:pathData="M20,6h-4V4c0,-1.11 -0.89,-2 -2,-2h-4C8.89,2 8,2.89 8,4v2H4C2.89,6 2.01,6.89 2.01,8L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2V8C22,6.89 21.11,6 20,6zM10,4h4v2h-4V4zM20,19H4V8h16V19z"/>
+ android:fillColor="@android:color/white"
+ android:pathData="M20,6h-4V4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8 C22,6.9,21.1,6,20,6z M10,4h4v2h-4V4z M20,19H4V8h16V19z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 12 C 12.8284271247 12 13.5 12.6715728753 13.5 13.5 C 13.5 14.3284271247 12.8284271247 15 12 15 C 11.1715728753 15 10.5 14.3284271247 10.5 13.5 C 10.5 12.6715728753 11.1715728753 12 12 12 Z" />
</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_corp_icon_badge_color.xml b/core/res/res/drawable/ic_corp_icon_badge_color.xml
index 6dba277..bb2d117 100644
--- a/core/res/res/drawable/ic_corp_icon_badge_color.xml
+++ b/core/res/res/drawable/ic_corp_icon_badge_color.xml
@@ -19,12 +19,15 @@
android:height="64dp"
android:viewportWidth="64"
android:viewportHeight="64">
-
- <path
- android:fillColor="#fcfcfc"
- android:strokeColor="#e8eaed"
- android:strokeWidth="0.25"
- android:pathData="M62,50A12,12,0,1,1,50,38,12,12,0,0,1,62,50" />
- <path
- android:pathData="M 0 0 H 64 V 64 H 0 V 0 Z" />
+ <group
+ android:scaleX=".24"
+ android:scaleY=".24"
+ android:translateX="38"
+ android:translateY="38">
+ <path
+ android:fillColor="#fcfcfc"
+ android:strokeColor="#e8eaed"
+ android:strokeWidth="0.25"
+ android:pathData="@string/config_icon_mask" />
+ </group>
</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_corp_icon_badge_shadow.xml b/core/res/res/drawable/ic_corp_icon_badge_shadow.xml
index f33ed1f..cb29f6c 100644
--- a/core/res/res/drawable/ic_corp_icon_badge_shadow.xml
+++ b/core/res/res/drawable/ic_corp_icon_badge_shadow.xml
@@ -19,31 +19,52 @@
android:height="64dp"
android:viewportWidth="64"
android:viewportHeight="64">
-
- <path
- android:fillColor="#000000"
- android:fillAlpha="0.06"
- android:strokeAlpha="0.06"
- android:strokeWidth="1"
- android:pathData="M62,51.25a12,12,0,1,1-12-12,12,12,0,0,1,12,12" />
- <path
- android:pathData="M 0 0 H 64 V 64 H 0 V 0 Z" />
- <path
- android:fillColor="#000000"
- android:fillAlpha="0.06"
- android:strokeAlpha="0.06"
- android:strokeWidth="1"
- android:pathData="M62,52.28A12,12,0,1,1,50.53,39.76,12,12,0,0,1,62,52.28" />
- <path
- android:fillColor="#000000"
- android:fillAlpha="0.06"
- android:strokeAlpha="0.06"
- android:strokeWidth="1"
- android:pathData="M62,50.75a12,12,0,1,1-12-12,12,12,0,0,1,12,12" />
- <path
- android:fillColor="#000000"
- android:fillAlpha="0.06"
- android:strokeAlpha="0.06"
- android:strokeWidth="1"
- android:pathData="M62,50.25a12,12,0,1,1-12-12,12,12,0,0,1,12,12" />
+ <group
+ android:scaleX=".24"
+ android:scaleY=".24"
+ android:translateX="38"
+ android:translateY="39.25">
+ <path
+ android:fillColor="#000000"
+ android:fillAlpha="0.06"
+ android:strokeAlpha="0.06"
+ android:strokeWidth="1"
+ android:pathData="@string/config_icon_mask" />
+ </group>
+ <group
+ android:scaleX=".24"
+ android:scaleY=".24"
+ android:translateX="38"
+ android:translateY="39.75">
+ <path
+ android:fillColor="#000000"
+ android:fillAlpha="0.06"
+ android:strokeAlpha="0.06"
+ android:strokeWidth="1"
+ android:pathData="@string/config_icon_mask" />
+ </group>
+ <group
+ android:scaleX=".24"
+ android:scaleY=".24"
+ android:translateX="38"
+ android:translateY="38.75">
+ <path
+ android:fillColor="#000000"
+ android:fillAlpha="0.06"
+ android:strokeAlpha="0.06"
+ android:strokeWidth="1"
+ android:pathData="@string/config_icon_mask" />
+ </group>
+ <group
+ android:scaleX=".24"
+ android:scaleY=".24"
+ android:translateX="38"
+ android:translateY="38.25">
+ <path
+ android:fillColor="#000000"
+ android:fillAlpha="0.06"
+ android:strokeAlpha="0.06"
+ android:strokeWidth="1"
+ android:pathData="@string/config_icon_mask" />
+ </group>
</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_hotspot_transient_animation.xml b/core/res/res/drawable/ic_hotspot_transient_animation.xml
new file mode 100644
index 0000000..efbdfdb
--- /dev/null
+++ b/core/res/res/drawable/ic_hotspot_transient_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_hotspot_transient_animation_drawable">
+ <target android:name="_R_G_L_0_G_D_0_P_0"
+ android:animation="@anim/ic_hotspot_transient_animation_0"/>
+ <target android:name="_R_G_L_0_G_D_1_P_0"
+ android:animation="@anim/ic_hotspot_transient_animation_1"/>
+ <target android:name="_R_G_L_0_G_D_2_P_0"
+ android:animation="@anim/ic_hotspot_transient_animation_2"/>
+ <target android:name="time_group"
+ android:animation="@anim/ic_hotspot_transient_animation_3"/>
+</animated-vector>
diff --git a/core/res/res/drawable/ic_hotspot_transient_animation_drawable.xml b/core/res/res/drawable/ic_hotspot_transient_animation_drawable.xml
new file mode 100644
index 0000000..d81abbb
--- /dev/null
+++ b/core/res/res/drawable/ic_hotspot_transient_animation_drawable.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:width="24dp" android:viewportHeight="24"
+ android:viewportWidth="24">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12"
+ android:translateY="12">
+ <group android:name="_R_G_L_0_G" android:translateX="-10"
+ android:translateY="-9">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M10 8 C8.9,8 8,8.9 8,10 C8,10.55 8.23,11.05 8.59,11.41 C8.95,11.77 9.45,12 10,12 C10.55,12 11.05,11.77 11.41,11.41 C11.77,11.05 12,10.55 12,10 C12,8.9 11.1,8 10,8c "/>
+ <path android:name="_R_G_L_0_G_D_1_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M10 4 C6.69,4 4,6.69 4,10 C4,11.66 4.68,13.15 5.76,14.24 C5.76,14.24 7.18,12.82 7.18,12.82 C6.45,12.1 6,11.11 6,10 C6,7.79 7.79,6 10,6 C12.21,6 14,7.79 14,10 C14,11.11 13.55,12.1 12.82,12.82 C12.82,12.82 14.24,14.24 14.24,14.24 C15.32,13.15 16,11.66 16,10 C16,6.69 13.31,4 10,4c "/>
+ <path android:name="_R_G_L_0_G_D_2_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M10 0 C4.48,0 0,4.48 0,10 C0,12.76 1.12,15.26 2.93,17.07 C2.93,17.07 4.34,15.66 4.34,15.66 C2.9,14.21 2,12.21 2,10 C2,5.58 5.58,2 10,2 C14.42,2 18,5.58 18,10 C18,12.21 17.1,14.2 15.65,15.65 C15.65,15.65 17.06,17.06 17.06,17.06 C18.88,15.26 20,12.76 20,10 C20,4.48 15.52,0 10,0c "/>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+</vector>
diff --git a/core/res/res/drawable/ic_lock.xml b/core/res/res/drawable/ic_lock.xml
index fed0e0d..7582d5f 100644
--- a/core/res/res/drawable/ic_lock.xml
+++ b/core/res/res/drawable/ic_lock.xml
@@ -16,12 +16,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
- android:viewportWidth="32"
- android:viewportHeight="32">
+ android:viewportWidth="32.0"
+ android:viewportHeight="32.0">
<path
- android:fillColor="#000"
- android:pathData="M16,20m-2.7,0a2.7,2.7 0,1 1,5.4 0a2.7,2.7 0,1 1,-5.4 0"/>
+ android:fillColor="#FF000000"
+ android:pathData="M16,20m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
<path
- android:fillColor="#000"
- android:pathData="M24,10.7h-2V7.3c0,-3.3 -2.7,-6 -6,-6s-6,2.7 -6,6v3.3H8c-1.5,0 -2.7,1.2 -2.7,2.7v13.3c0,1.5 1.2,2.7 2.7,2.7h16c1.5,0 2.7,-1.2 2.7,-2.7V13.3C26.7,11.9 25.5,10.7 24,10.7zM12.7,7.3C12.7,5.5 14.2,4 16,4s3.3,1.5 3.3,3.3v3.3h-6.7V7.3zM24,26.7H8V13.3h2h12h2V26.7z"/>
-</vector>
+ android:fillColor="#FF000000"
+ android:pathData="M24,11h-2.3V7.3c0,-3.1 -2.5,-5.7 -5.7,-5.7c-3.1,0 -5.7,2.5 -5.7,5.7V11H8c-1.3,0 -2.3,1 -2.3,2.3v13.3c0,1.3 1,2.3 2.3,2.3h16c1.3,0 2.3,-1 2.3,-2.3V13.3C26.3,12 25.3,11 24,11zM12.3,7.3c0,-2 1.6,-3.7 3.7,-3.7c2,0 3.7,1.6 3.7,3.7V11h-7.3V7.3zM24.3,26.7c0,0.2 -0.1,0.3 -0.3,0.3H8c-0.2,0 -0.3,-0.1 -0.3,-0.3V13.3C7.7,13.1 7.8,13 8,13h16c0.2,0 0.3,0.1 0.3,0.3V26.7z"/>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_lock_open.xml b/core/res/res/drawable/ic_lock_open.xml
index 494fd6a..e0deb598 100644
--- a/core/res/res/drawable/ic_lock_open.xml
+++ b/core/res/res/drawable/ic_lock_open.xml
@@ -16,12 +16,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
- android:viewportWidth="32"
- android:viewportHeight="32">
+ android:viewportWidth="32.0"
+ android:viewportHeight="32.0">
<path
- android:fillColor="#000"
- android:pathData="M16,20m-2.67,0a2.67,2.67 0,1 1,5.34 0a2.67,2.67 0,1 1,-5.34 0"/>
+ android:fillColor="#FF000000"
+ android:pathData="M16,20m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
<path
- android:fillColor="#000"
- android:pathData="M24.67,1.33a6,6 0,0 0,-6 6v3.34L8,10.67a2.67,2.67 0,0 0,-2.67 2.66L5.33,26.67A2.67,2.67 0,0 0,8 29.33L24,29.33a2.67,2.67 0,0 0,2.67 -2.66L26.67,13.33A2.67,2.67 0,0 0,24 10.67L21.33,10.67L21.33,7.33a3.34,3.34 0,0 1,6.67 0L28,8h2.67L30.67,7.33A6,6 0,0 0,24.67 1.33ZM24,13.33L24,26.67L8,26.67L8,13.33Z"/>
+ android:fillColor="#FF000000"
+ android:pathData="M25.3,1.7c-3.1,0 -5.7,2.5 -5.7,5.7V11H8c-1.3,0 -2.3,1 -2.3,2.3v13.3c0,1.3 1,2.3 2.3,2.3h16c1.3,0 2.3,-1 2.3,-2.3V13.3c0,-1.3 -1,-2.3 -2.3,-2.3h-2.3V7.3c0,-2 1.6,-3.7 3.7,-3.7c2,0 3.7,1.6 3.7,3.7V8h2V7.3C31,4.2 28.5,1.7 25.3,1.7zM24.3,13.3v13.3c0,0.2 -0.1,0.3 -0.3,0.3H8c-0.2,0 -0.3,-0.1 -0.3,-0.3V13.3C7.7,13.1 7.8,13 8,13h16C24.2,13 24.3,13.1 24.3,13.3z"/>
</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_cellular.xml b/core/res/res/drawable/ic_signal_cellular.xml
new file mode 100644
index 0000000..fdde0d1
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+<level-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:minLevel="0" android:maxLevel="0" android:drawable="@drawable/ic_signal_cellular_0_4_bar" />
+ <item android:minLevel="1" android:maxLevel="1" android:drawable="@drawable/ic_signal_cellular_1_4_bar" />
+ <item android:minLevel="2" android:maxLevel="2" android:drawable="@drawable/ic_signal_cellular_2_4_bar" />
+ <item android:minLevel="3" android:maxLevel="3" android:drawable="@drawable/ic_signal_cellular_3_4_bar" />
+ <item android:minLevel="4" android:maxLevel="4" android:drawable="@drawable/ic_signal_cellular_4_4_bar" />
+ <item android:minLevel="10" android:maxLevel="10" android:drawable="@drawable/ic_signal_cellular_0_5_bar" />
+ <item android:minLevel="11" android:maxLevel="11" android:drawable="@drawable/ic_signal_cellular_1_5_bar" />
+ <item android:minLevel="12" android:maxLevel="12" android:drawable="@drawable/ic_signal_cellular_2_5_bar" />
+ <item android:minLevel="13" android:maxLevel="13" android:drawable="@drawable/ic_signal_cellular_3_5_bar" />
+ <item android:minLevel="14" android:maxLevel="14" android:drawable="@drawable/ic_signal_cellular_4_5_bar" />
+ <item android:minLevel="15" android:maxLevel="15" android:drawable="@drawable/ic_signal_cellular_5_5_bar" />
+</level-list>
diff --git a/core/res/res/drawable/ic_signal_cellular_0_4_bar.xml b/core/res/res/drawable/ic_signal_cellular_0_4_bar.xml
new file mode 100644
index 0000000..9f6fa2f
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_0_4_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,7v13H7L20,7 M22,2L2,22h20V2L22,2z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_cellular_0_5_bar.xml b/core/res/res/drawable/ic_signal_cellular_0_5_bar.xml
new file mode 100644
index 0000000..9f6fa2f
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_0_5_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,7v13H7L20,7 M22,2L2,22h20V2L22,2z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_cellular_1_4_bar.xml b/core/res/res/drawable/ic_signal_cellular_1_4_bar.xml
new file mode 100644
index 0000000..c0fe536
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_1_4_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,7v13H7L20,7 M22,2L2,22h20V2L22,2z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 11 13 L 2 22 L 11 22 Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_cellular_1_5_bar.xml b/core/res/res/drawable/ic_signal_cellular_1_5_bar.xml
new file mode 100644
index 0000000..816da22
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_1_5_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,7V20H7L20,7m2-5L2,22H22V2Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8.72,15.28,2,22H8.72V15.28Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_cellular_2_4_bar.xml b/core/res/res/drawable/ic_signal_cellular_2_4_bar.xml
new file mode 100644
index 0000000..69a966b
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_2_4_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,7v13H7L20,7 M22,2L2,22h20V2L22,2z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 13 11 L 2 22 L 13 22 Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_cellular_2_5_bar.xml b/core/res/res/drawable/ic_signal_cellular_2_5_bar.xml
new file mode 100644
index 0000000..02c7a43
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_2_5_bar.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,7V20H7L20,7m2-5L2,22H22V2Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 11.45 12.55 L 2 22 L 11.45 22 L 11.45 12.55 Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_cellular_3_4_bar.xml b/core/res/res/drawable/ic_signal_cellular_3_4_bar.xml
new file mode 100644
index 0000000..46ce47c
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_3_4_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,7v13H7L20,7 M22,2L2,22h20V2L22,2z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 2 22 L 16 22 L 16 21 L 16 20 L 16 11 L 16 10 L 16 8 Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_cellular_3_5_bar.xml b/core/res/res/drawable/ic_signal_cellular_3_5_bar.xml
new file mode 100644
index 0000000..37435e6
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_3_5_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,7V20H7L20,7m2-5L2,22H22V2Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 14.96 9.04 L 2 22 L 14.96 22 L 14.96 9.04 Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_cellular_4_4_bar.xml b/core/res/res/drawable/ic_signal_cellular_4_4_bar.xml
new file mode 100644
index 0000000..f93e40d
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_4_4_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,2L2,22h20V2L22,2z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_cellular_4_5_bar.xml b/core/res/res/drawable/ic_signal_cellular_4_5_bar.xml
new file mode 100644
index 0000000..6dc3646
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_4_5_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,7V20H7L20,7m2-5L2,22H22V2Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 18.48 5.52 L 2 22 L 18.48 22 L 18.48 5.52 Z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_cellular_5_5_bar.xml b/core/res/res/drawable/ic_signal_cellular_5_5_bar.xml
new file mode 100644
index 0000000..f93e40d
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_5_5_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,2L2,22h20V2L22,2z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_signal_wifi_transient_animation.xml b/core/res/res/drawable/ic_signal_wifi_transient_animation.xml
new file mode 100644
index 0000000..0219ae5
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_wifi_transient_animation.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open 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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_signal_wifi_transient_animation_drawable">
+ <target android:name="_R_G_L_4_G_N_1_T_0"
+ android:animation="@anim/ic_signal_wifi_transient_animation_0" />
+ <target android:name="_R_G_L_3_G_N_1_T_0"
+ android:animation="@anim/ic_signal_wifi_transient_animation_1" />
+ <target android:name="_R_G_L_3_G_N_1_T_0"
+ android:animation="@anim/ic_signal_wifi_transient_animation_2" />
+ <target android:name="_R_G_L_2_G_N_1_T_0"
+ android:animation="@anim/ic_signal_wifi_transient_animation_3" />
+ <target android:name="_R_G_L_2_G_N_1_T_0"
+ android:animation="@anim/ic_signal_wifi_transient_animation_4" />
+ <target android:name="_R_G_L_1_G_N_1_T_0"
+ android:animation="@anim/ic_signal_wifi_transient_animation_5" />
+ <target android:name="_R_G_L_1_G_N_1_T_0"
+ android:animation="@anim/ic_signal_wifi_transient_animation_6" />
+ <target android:name="_R_G_L_0_G_N_1_T_0"
+ android:animation="@anim/ic_signal_wifi_transient_animation_7" />
+ <target android:name="time_group"
+ android:animation="@anim/ic_signal_wifi_transient_animation_8" />
+</animated-vector>
diff --git a/core/res/res/drawable/ic_signal_wifi_transient_animation_drawable.xml b/core/res/res/drawable/ic_signal_wifi_transient_animation_drawable.xml
new file mode 100644
index 0000000..9cd4925
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_wifi_transient_animation_drawable.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_4_G_N_1_T_0" android:translateX="12"
+ android:translateY="12">
+ <group android:name="_R_G_L_4_G" android:translateX="-12.25"
+ android:translateY="-10.25">
+ <path android:name="_R_G_L_4_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12.25 2.25 C15.67,2.25 18.98,3.52 21.55,5.78 C21.55,5.78 12.25,17.1 12.25,17.1 C12.25,17.1 2.95,5.78 2.95,5.78 C5.52,3.52 8.83,2.25 12.25,2.25c M12.25 0.25 C7.5,0.25 3.22,2.33 0.25,5.64 C0.25,5.64 12.25,20.25 12.25,20.25 C12.25,20.25 24.25,5.64 24.25,5.64 C21.28,2.33 17,0.25 12.25,0.25c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_3_G_N_1_T_0" android:translateX="12"
+ android:translateY="12">
+ <group android:name="_R_G_L_3_G" android:translateX="-12.25"
+ android:translateY="-10.25">
+ <path android:name="_R_G_L_3_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12.25 2.25 C15.65,2.25 18.95,3.55 21.55,5.75 C21.55,5.75 12.25,17.05 12.25,17.05 C12.25,17.05 2.95,5.75 2.95,5.75 C5.55,3.55 8.85,2.25 12.25,2.25c M12.25 0.25 C7.45,0.25 3.25,2.35 0.25,5.65 C0.25,5.65 12.25,20.25 12.25,20.25 C12.25,20.25 24.25,5.65 24.25,5.65 C21.25,2.35 17.05,0.25 12.25,0.25c "/>
+ <path android:name="_R_G_L_3_G_D_1_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12.25 11.25 C10.15,11.25 8.15,12.15 6.85,13.65 C6.85,13.65 12.25,20.25 12.25,20.25 C12.25,20.25 17.65,13.65 17.65,13.65 C16.35,12.15 14.35,11.25 12.25,11.25c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_2_G_N_1_T_0" android:translateX="12"
+ android:translateY="12">
+ <group android:name="_R_G_L_2_G" android:translateX="-12.25"
+ android:translateY="-10.25">
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12.25 2.25 C15.65,2.25 18.95,3.55 21.55,5.75 C21.55,5.75 12.25,17.05 12.25,17.05 C12.25,17.05 2.95,5.75 2.95,5.75 C5.55,3.55 8.85,2.25 12.25,2.25c M12.25 0.25 C7.45,0.25 3.25,2.35 0.25,5.65 C0.25,5.65 12.25,20.25 12.25,20.25 C12.25,20.25 24.25,5.65 24.25,5.65 C21.25,2.35 17.05,0.25 12.25,0.25c "/>
+ <path android:name="_R_G_L_2_G_D_1_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12.25 8.25 C9.45,8.25 6.75,9.45 5.05,11.45 C5.05,11.45 12.25,20.25 12.25,20.25 C12.25,20.25 19.45,11.45 19.45,11.45 C17.75,9.45 15.05,8.25 12.25,8.25c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="12"
+ android:translateY="12">
+ <group android:name="_R_G_L_1_G" android:translateX="-12.25"
+ android:translateY="-10.25">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12.25 2.25 C15.65,2.25 18.95,3.55 21.55,5.75 C21.55,5.75 12.25,17.05 12.25,17.05 C12.25,17.05 2.95,5.75 2.95,5.75 C5.55,3.55 8.85,2.25 12.25,2.25c M12.25 0.25 C7.45,0.25 3.25,2.35 0.25,5.65 C0.25,5.65 12.25,20.25 12.25,20.25 C12.25,20.25 24.25,5.65 24.25,5.65 C21.25,2.35 17.05,0.25 12.25,0.25c "/>
+ <path android:name="_R_G_L_1_G_D_1_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12.25 5.25 C8.75,5.25 5.45,6.75 3.25,9.25 C3.25,9.25 12.25,20.25 12.25,20.25 C12.25,20.25 21.25,9.25 21.25,9.25 C19.05,6.75 15.75,5.25 12.25,5.25c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12"
+ android:translateY="12">
+ <group android:name="_R_G_L_0_G" android:translateX="-12.25"
+ android:translateY="-10.25">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12.25 2.25 C15.65,2.25 18.95,3.55 21.55,5.75 C21.55,5.75 12.25,17.05 12.25,17.05 C12.25,17.05 2.95,5.75 2.95,5.75 C5.55,3.55 8.85,2.25 12.25,2.25c M12.25 0.25 C7.45,0.25 3.25,2.35 0.25,5.65 C0.25,5.65 12.25,20.25 12.25,20.25 C12.25,20.25 24.25,5.65 24.25,5.65 C21.25,2.35 17.05,0.25 12.25,0.25c "/>
+ <path android:name="_R_G_L_0_G_D_1_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12.25 5.25 C8.75,5.25 5.45,6.75 3.25,9.25 C3.25,9.25 12.25,20.25 12.25,20.25 C12.25,20.25 21.25,9.25 21.25,9.25 C19.05,6.75 15.75,5.25 12.25,5.25c "/>
+ <path android:name="_R_G_L_0_G_D_2_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12.25 0.25 C7.45,0.25 3.25,2.35 0.25,5.65 C0.25,5.65 12.25,20.25 12.25,20.25 C12.25,20.25 24.25,5.65 24.25,5.65 C21.25,2.35 17.05,0.25 12.25,0.25c "/>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/popup_background_material.xml b/core/res/res/drawable/popup_background_material.xml
index b1f0cf5..9ad7bfc 100644
--- a/core/res/res/drawable/popup_background_material.xml
+++ b/core/res/res/drawable/popup_background_material.xml
@@ -20,6 +20,6 @@
<corners
android:radius="2dp" />
<solid
- android:color="?attr/colorBackground" />
+ android:color="?attr/colorPopupBackground" />
</shape>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/core/res/res/interpolator/transient_interpolator.xml
similarity index 64%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to core/res/res/interpolator/transient_interpolator.xml
index 8b8258f..653a8cf 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/core/res/res/interpolator/transient_interpolator.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2019 The Android Open Source Project
~
@@ -14,13 +13,5 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
\ No newline at end of file
diff --git a/core/res/res/layout-car/car_preference.xml b/core/res/res/layout-car/car_preference.xml
index ae3d63b..b138f4d 100644
--- a/core/res/res/layout-car/car_preference.xml
+++ b/core/res/res/layout-car/car_preference.xml
@@ -27,20 +27,20 @@
<com.android.internal.widget.PreferenceImageView
android:id="@id/icon"
- android:layout_width="@*android:dimen/car_primary_icon_size"
- android:layout_height="@*android:dimen/car_primary_icon_size"
+ android:layout_width="@dimen/car_preference_icon_size"
+ android:layout_height="@dimen/car_preference_icon_size"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
- android:layout_marginBottom="@*android:dimen/car_padding_2"
+ android:layout_marginBottom="@dimen/car_preference_row_vertical_margin"
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
- android:layout_marginTop="@android:dimen/car_padding_2"/>
+ android:layout_marginTop="@dimen/car_preference_row_vertical_margin"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
- android:layout_marginBottom="@*android:dimen/car_padding_2"
- android:layout_marginTop="@*android:dimen/car_padding_2"
+ android:layout_marginBottom="@dimen/car_preference_row_vertical_margin"
+ android:layout_marginTop="@dimen/car_preference_row_vertical_margin"
android:layout_toEndOf="@id/icon"
android:layout_toStartOf="@id/widget_frame"
android:orientation="vertical">
diff --git a/core/res/res/layout-car/car_preference_category.xml b/core/res/res/layout-car/car_preference_category.xml
index d1f7342..b674487 100644
--- a/core/res/res/layout-car/car_preference_category.xml
+++ b/core/res/res/layout-car/car_preference_category.xml
@@ -22,25 +22,25 @@
android:background="?android:attr/selectableItemBackground"
android:focusable="true"
android:gravity="center_vertical"
- android:minHeight="@*android:dimen/car_card_header_height"
+ android:minHeight="@dimen/car_card_header_height"
android:orientation="horizontal"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingStart="?android:attr/listPreferredItemPaddingStart">
<com.android.internal.widget.PreferenceImageView
android:id="@id/icon"
- android:layout_width="@*android:dimen/car_primary_icon_size"
- android:layout_height="@*android:dimen/car_primary_icon_size"
+ android:layout_width="@dimen/car_preference_category_icon_size"
+ android:layout_height="@dimen/car_preference_category_icon_size"
android:layout_gravity="center_vertical"
- android:layout_marginBottom="@dimen/car_padding_2"
+ android:layout_marginBottom="@dimen/car_preference_row_vertical_margin"
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
- android:layout_marginTop="@*android:dimen/car_padding_2"/>
+ android:layout_marginTop="@dimen/car_preference_row_vertical_margin"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginBottom="@*android:dimen/car_padding_2"
- android:layout_marginTop="@*android:dimen/car_padding_2"
+ android:layout_marginBottom="@dimen/car_preference_row_vertical_margin"
+ android:layout_marginTop="@dimen/car_preference_row_vertical_margin"
android:orientation="vertical">
<TextView
diff --git a/core/res/res/layout/chooser_grid_preview_text.xml b/core/res/res/layout/chooser_grid_preview_text.xml
index e889e85..9c725b9 100644
--- a/core/res/res/layout/chooser_grid_preview_text.xml
+++ b/core/res/res/layout/chooser_grid_preview_text.xml
@@ -23,7 +23,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:paddingBottom="@dimen/chooser_view_spacing"
android:background="?android:attr/colorBackgroundFloating">
<RelativeLayout
@@ -60,7 +59,7 @@
android:minWidth="48dp"
android:minHeight="48dp"
android:clickable="true"
- android:background="?android:attr/selectableItemBackgroundBorderless">
+ style="?attr/borderlessButtonStyle">
<ImageView
android:layout_width="24dp"
@@ -91,6 +90,7 @@
android:orientation="horizontal"
android:layout_marginLeft="@dimen/chooser_edge_margin_normal"
android:layout_marginRight="@dimen/chooser_edge_margin_normal"
+ android:layout_marginBottom="@dimen/chooser_view_spacing"
android:minHeight="80dp"
android:background="@drawable/chooser_content_preview_rounded"
android:id="@+id/content_preview_title_layout">
diff --git a/core/res/res/layout/media_route_chooser_dialog.xml b/core/res/res/layout/media_route_chooser_dialog.xml
index d1c6267..cd1c74f 100644
--- a/core/res/res/layout/media_route_chooser_dialog.xml
+++ b/core/res/res/layout/media_route_chooser_dialog.xml
@@ -40,7 +40,7 @@
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:paddingLeft="16dp"
+ android:paddingStart="16dp"
android:text="@string/media_route_chooser_searching" />
</LinearLayout>
diff --git a/core/res/res/layout/media_route_list_item.xml b/core/res/res/layout/media_route_list_item.xml
index bdca433..e8460db 100644
--- a/core/res/res/layout/media_route_list_item.xml
+++ b/core/res/res/layout/media_route_list_item.xml
@@ -34,6 +34,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
+ android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceMedium"
android:duplicateParentState="true" />
@@ -42,6 +43,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
+ android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceSmall"
android:duplicateParentState="true" />
</LinearLayout>
diff --git a/core/res/res/layout/resolve_grid_item.xml b/core/res/res/layout/resolve_grid_item.xml
index 256d94e..7098c95 100644
--- a/core/res/res/layout/resolve_grid_item.xml
+++ b/core/res/res/layout/resolve_grid_item.xml
@@ -23,7 +23,7 @@
android:minHeight="100dp"
android:gravity="center"
android:paddingTop="24dp"
- android:paddingBottom="8dp"
+ android:paddingBottom="12dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:focusable="true"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index e4dd53f..2bd7c8a 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Skryf jou gesig asseblief weer in."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Kan nie meer gesig herken nie. Probeer weer."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Te eenders. Verander asseblief jou pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Kyk asseblief meer reguit na die skerm."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Kyk asseblief meer reguit na die skerm."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Hou asseblief jou kop regop."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Hou die spasie tussen jou kop en foon oop."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Maak asseblief die kamera skoon."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Draai jou kop \'n bietjie minder."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Draai jou kop \'n bietjie minder."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Draai jou kop \'n bietjie minder."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Verwyder enigiets wat jou gesig versteek."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Maak die sensor op die skerm se borand skoon."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Kan nie gesig verifieer nie. Hardeware nie beskikbaar nie."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> lêer</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Regstreekse deling is nie beskikbaar nie"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Programmelys"</string>
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index f3bc422..44b58cf 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"እባክዎ ፊትዎን እንደገና ያስመዝግቡ"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"ከእንግዲህ ፊትን ለይቶ ማወቅ አይችልም። እንደገና ይሞክሩ።"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"በጣም ይመሳሰላል፣ እባክዎ የእርስዎን ፎቶ አነሳስ ይለውጡ"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"እባክዎ ወደ ማያ ገጹ በቀጥታ ይመልከቱ።"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"እባክዎ ወደ ማያ ገጹ በቀጥታ ይመልከቱ።"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"እባክዎ ጭንቅላትዎን ቀጥ ያድርጉ።"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"በእርስዎ ጭንቅላት እና በስልኩ መካከል ያለውን ክፍተት ያጽዱ።"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"እባክዎ ካሜራውን ያፅዱት።"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"ጭንቅላትዎን ትንሽ ብቻ ያዙሩት።"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ጭንቅላትዎን ትንሽ ብቻ ያዙሩት።"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ጭንቅላትዎን ትንሽ ብቻ ያዙሩት።"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"የእርስዎን ፊት የሚደብቀውን ሁሉንም ነገር በማስወገድ ላይ"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"በማያ ገጹ ላይኛው ጫፍ ላይ ዳሳሹን ያጽዱ።"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"መልክን ማረጋገጥ አይቻልም። ሃርድዌር የለም።"</string>
@@ -2027,4 +2027,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ፋይሎች</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"ቀጥታ ማጋራት አይገኝም"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"የመተግበሪያዎች ዝርዝር"</string>
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index ed64ad8..8b409ca 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -68,7 +68,7 @@
<string name="CwMmi" msgid="9129678056795016867">"انتظار المكالمة"</string>
<string name="BaMmi" msgid="455193067926770581">"حظر الاتصال"</string>
<string name="PwdMmi" msgid="7043715687905254199">"تغيير كلمة المرور"</string>
- <string name="PinMmi" msgid="3113117780361190304">"تغيير رمز PIN"</string>
+ <string name="PinMmi" msgid="3113117780361190304">"تغيير رقم التعريف الشخصي"</string>
<string name="CnipMmi" msgid="3110534680557857162">"رقم الاتصال موجود"</string>
<string name="CnirMmi" msgid="3062102121430548731">"رقم الاتصال محظور"</string>
<string name="ThreeWCMmi" msgid="9051047170321190368">"اتصال ثلاثي"</string>
@@ -583,11 +583,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"يُرجى إعادة تسجيل وجهك."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"لم يعُد يمكن التعرّف على الوجه. حاول مرة أخرى."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"الوجه مشابه جدًا، يُرجى تغيير وضعيتك."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"يُرجى النظر إلى الشاشة مباشرة أكثر."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"يُرجى النظر إلى الشاشة مباشرة أكثر."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"يُرجى تثبيت الرأس في وضع عمودي."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"يُرجى إخلاء المنطقة بين رأسك والهاتف."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"يُرجى تنظيف الكاميرا."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"حرّك رأسك قليلاً نحو الأمام مباشرة."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"حرّك رأسك قليلاً نحو الأمام مباشرة."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"حرّك رأسك قليلاً نحو الوسط."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"عليك بإزالة أي شيء يُخفي وجهك."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"نظِّف المستشعر أعلى الشاشة."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"يتعذّر التحقُّق من الوجه. الجهاز غير مُتاح."</string>
@@ -2171,4 +2171,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> وملف (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"لا تتوفّر إمكانية المشاركة المباشرة."</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"قائمة التطبيقات"</string>
</resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 6a219f3..cf3745f 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -571,11 +571,14 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"আপোনাৰ মুখমণ্ডল পুনৰ পঞ্জীয়ন কৰক।"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"মুখমণ্ডল আৰু চিনাক্ত কৰিব নোৱাৰি। আকৌ চেষ্টা কৰক।"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"একে ধৰণৰ হৈছে, অনুগ্ৰহ কৰি আপোনাৰ প’জটো সলনি কৰক।"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"অনুগ্ৰহ কৰি পোনে পোনে কেমেৰালৈ চাওক।"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"অনুগ্ৰহ কৰি পোনে পোনে কেমেৰালৈ চাওক।"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"অনুগ্ৰহ কৰি আপোনাৰ মূৰটো উলম্বভাৱে চিধা কৰক।"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"আপোনাৰ মূৰ আৰু ফ’নৰ মাজত যদি কিবা আছে আঁতৰাওক।"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"কেমেৰা পৰিস্কাৰ কৰক।"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"আপোনাৰ মূৰটো সামান্য কমকৈ ঘূৰাওক।"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"আপোনাৰ মূৰটো সামান্য কমকৈ ঘূৰাওক।"</string>
+ <!-- no translation found for face_acquired_roll_too_extreme (6312973147689664409) -->
+ <skip />
+ <!-- no translation found for face_acquired_obscured (5357207702967893283) -->
+ <skip />
+ <!-- no translation found for face_acquired_sensor_dirty (2535761002815565222) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"মুখমণ্ডল সত্যাপন কৰিব পৰা নগ’ল। হাৰ্ডৱেৰ নাই।"</string>
@@ -2027,4 +2030,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g>টা ফাইল</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"পোনপটীয়া শ্বেয়াৰৰ সুবিধা নাই"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"এপ্সমূহৰ সূচী"</string>
</resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index bca244f..29e453f 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Üzünüzü yenidən qeydiyyatdan keçirin."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Üzü artıq tanımaq olmur. Yenidən cəhd edin."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Digəri ilə oxşardır, pozanızı dəyişin."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Birbaşa ekrana baxın."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Birbaşa ekrana baxın."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Başınızı şaquli istiqamətdə qaldırın."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Başınız və telefon arasında məsafə olmamalıdır."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Kameranı təmizləyin."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Başınızı bir az döndərin."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Başınızı bir az döndərin."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Başınızı bir az döndərin."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Üzünüzü gizlədən maneələri kənarlaşdırın."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Ekranın yuxarı küncündəki sensoru təmizləyin."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Üz doğrulanmadı. Avadanlıq əlçatan deyil."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> fayl</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Birbaşa paylaşım əlçatan deyil"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Tətbiq siyahısı"</string>
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index d4be6e7..e298556f 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -574,11 +574,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Ponovo registrujte lice."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Više ne može da se prepozna lice. Probajte ponovo."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Previše je slično, promenite pozu."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Gledajte pravo u ekran."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Gledajte pravo u ekran."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Ispravite glavu."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Oslobodite prostor između glave i telefona."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Očistite kameru."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Malo manje pomerite glavu."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Malo manje pomerite glavu."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Malo manje pomerite glavu."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Uklonite sve što vam zaklanja lice."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Očistite senzor na gornjoj ivici ekrana."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Provera lica nije uspela. Hardver nije dostupan."</string>
@@ -899,7 +899,7 @@
<string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
<string name="granularity_label_character" msgid="7336470535385009523">"znak"</string>
<string name="granularity_label_word" msgid="7075570328374918660">"reč"</string>
- <string name="granularity_label_link" msgid="5815508880782488267">"veza"</string>
+ <string name="granularity_label_link" msgid="5815508880782488267">"link"</string>
<string name="granularity_label_line" msgid="5764267235026120888">"red"</string>
<string name="factorytest_failed" msgid="5410270329114212041">"Fabričko testiranje nije uspelo"</string>
<string name="factorytest_not_system" msgid="4435201656767276723">"Radnja FACTORY_TEST je podržana samo za pakete instalirane u direktorijumu /system/app."</string>
@@ -2063,4 +2063,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> i još <xliff:g id="COUNT_3">%d</xliff:g> datoteka</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Direktno deljenje nije dostupno"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lista aplikacija"</string>
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 4fa9178..7c4060c 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -468,9 +468,9 @@
<string name="permlab_setWallpaperHints" msgid="3278608165977736538">"наладка памеру шпалер"</string>
<string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"Дазваляе прыкладанням задаваць падказкі па памеры сістэмных шпалер."</string>
<string name="permlab_setTimeZone" msgid="2945079801013077340">"усталёўваць часавы пояс"</string>
- <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"Дазваляе прыкладанням змяняць гадзінны пояс планшэта."</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"Дазваляе праграмам змяняць часавы пояс планшэта."</string>
<string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"Дазваляе праграме змяняць часавы пояс тэлевізара."</string>
- <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Дазваляе прыкладанню змяняць гадзінны пояс тэлефона."</string>
+ <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Дазваляе праграме змяняць часавы пояс тэлефона."</string>
<string name="permlab_getAccounts" msgid="1086795467760122114">"пошук уліковых запісаў на прыладзе"</string>
<string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Дазваляе прыкладанню атрымлiваць спіс уліковых запісаў, вядомых планшэту. Сярод iх могуць быць улiковыя запiсы, створаныя прыкладаннямi, якiя вы ўсталявалi."</string>
<string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"Дазваляе праграме атрымлiваць спіс уліковых запісаў, вядомых тэлевізару. Сярод iх могуць быць любыя ўлiковыя запiсы, створаныя праграмамі, якiя вы ўсталявалi."</string>
@@ -577,11 +577,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Паўтарыце рэгістрацыю твару."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Не ўдаецца распазнаць твар. Паўтарыце спробу."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Не бачна розніцы. Памяняйце позу."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Глядзіце прама на экран."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Глядзіце прама на экран."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Выраўнуйце галаву."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Прыбярыце ўсё лішняе паміж тварам і тэлефонам."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Пачысціце камеру."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Вы занадта моцна павярнулі галаву."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Галава не ў цэнтры."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Вы занадта моцна павярнулі галаву."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Прыміце ўсё, што закрывае ваш твар."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Ачысціце датчык уверсе экрана."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Твар не спраўджаны. Абсталяванне недаступнае."</string>
@@ -2099,4 +2099,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> файла</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Непасрэднае абагульванне недаступнае"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Спіс праграм"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index aa4ca4c..4663387 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Моля, регистрирайте лицето си отново."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Лицето не бе разпознато. Опитайте отново."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Позата ви е сходна с предишна. Моля, променете я."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Моля, гледайте точно към екрана."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Моля, гледайте точно към екрана."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Моля, изправете главата си."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Между лицето ви и телефона не трябва да има нищо."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Моля, почистете камерата."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Не завъртайте главата си толкова много."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Не завъртайте главата си толкова много."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Не завъртайте главата си толкова много."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Премахнете всичко, което закрива лицето ви."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Изчистете сензора в горния край на екрана."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Лицето не може да се потвърди. Хардуерът не е налице."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> файл</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Няма възможност за директно споделяне"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Списък с приложения"</string>
</resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index d412268..32bb40b 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"আপনার মুখের ছবি আবার নথিভুক্ত করুন।"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"আর মুখ চিনতে পারবেন না। আবার চেষ্টা করুন।"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"একই ধরনের দেখতে, একটু অন্যদিকে ঘুরে দাঁড়ান।"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"সরাসরি স্ক্রিনের দিকে তাকান।"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"সরাসরি স্ক্রিনের দিকে তাকান।"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"মাথা সোজা করে রাখুন।"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"আপনার মুখের উপর কোনও আবরণ থাকলে সেটি সরিয়ে দিন।"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"ক্যামেরাটি পরিষ্কার করুন।"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"আপনার মাথাটি নিচের দিকে সামান্য নামান।"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"আপনার মাথাটি নিচের দিকে সামান্য নামান।"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"আপনার মাথাটি সামান্য ঘোরান।"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"আপনার ফেসকে আড়াল করে এমন সব কিছু সরিয়ে দিন।"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"স্ক্রিনের উপরের প্রান্তের সেন্সর মুছুন।"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ফেস যাচাই করা যায়নি। হার্ডওয়্যার উপলভ্য নেই।"</string>
@@ -1120,7 +1120,7 @@
<string name="dialog_alert_title" msgid="2049658708609043103">"খেয়াল করুন"</string>
<string name="loading" msgid="7933681260296021180">"লোড হচ্ছে..."</string>
<string name="capital_on" msgid="1544682755514494298">"চালু"</string>
- <string name="capital_off" msgid="6815870386972805832">"বন্ধ করুন"</string>
+ <string name="capital_off" msgid="6815870386972805832">"বন্ধ আছে"</string>
<string name="whichApplication" msgid="4533185947064773386">"এটি ব্যবহার করে ক্রিয়াকলাপ সম্পূর্ণ করুন"</string>
<string name="whichApplicationNamed" msgid="8260158865936942783">"%1$s ব্যবহার করে ক্রিয়াকলাপ সম্পূর্ণ করুন"</string>
<string name="whichApplicationLabel" msgid="7425855495383818784">"ক্রিয়াকলাপ সম্পূর্ণ করুন"</string>
@@ -1596,7 +1596,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"ওয়্যারলেস প্রদর্শন"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"কাস্ট করুন"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"ডিভাইসে সংযোগ করুন"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ডিভাইসে স্ক্রীণ কাস্ট করুন"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ডিভাইসে স্ক্রিন কাস্ট করুন"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"ডিভাইসগুলি সার্চ করা হচ্ছে…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"সেটিংস"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"সংযোগ বিচ্ছিন্ন করুন"</string>
@@ -1840,7 +1840,7 @@
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> পর্যন্ত"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> পর্যন্ত (পরবর্তী অ্যালার্ম)"</string>
<string name="zen_mode_forever" msgid="931849471004038757">"যতক্ষণ না আপনি বন্ধ করছেন"</string>
- <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"যতক্ষণ না পর্যন্ত আপনি বিরক্ত করবেন না বন্ধ করছেন"</string>
+ <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"যতক্ষণ পর্যন্ত না আপনি বিরক্ত করবেন না বন্ধ করছেন"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"সঙ্কুচিত করুন"</string>
<string name="zen_mode_feature_name" msgid="5254089399895895004">"বিরক্ত করবেন না"</string>
@@ -2028,4 +2028,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> এবং আরও <xliff:g id="COUNT_3">%d</xliff:g>টি ফাইল</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"সরাসরি শেয়ার করার সুবিধা নেই"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"অ্যাপের তালিকা"</string>
</resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index bfb52e1..9f65330 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -280,7 +280,7 @@
<string name="managed_profile_label" msgid="8947929265267690522">"Pređite na radni profil"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakti"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"pristupa vašim kontaktima"</string>
- <string name="permgrouprequest_contacts" msgid="6032805601881764300">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> pristup vašim kontaktima?"</string>
+ <string name="permgrouprequest_contacts" msgid="6032805601881764300">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> da pristupa vašim kontaktima?"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Lokacija"</string>
<string name="permgroupdesc_location" msgid="1346617465127855033">"pristupa lokaciji ovog uređaja"</string>
<string name="permgrouprequest_location" msgid="3788275734953323491">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> da pristupi lokaciji ovog uređaja?"</string>
@@ -295,22 +295,22 @@
<string name="permgrouprequest_sms" msgid="7168124215838204719">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> slanje i pregled SMS poruka?"</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"Pohrana"</string>
<string name="permgroupdesc_storage" msgid="637758554581589203">"pristupa slikama, medijskim fajlovima i fajlovima na vašem uređaju"</string>
- <string name="permgrouprequest_storage" msgid="7885942926944299560">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> pristup fotografijama, medijima i fajlovima na vašem uređaju?"</string>
+ <string name="permgrouprequest_storage" msgid="7885942926944299560">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> da pristupa fotografijama, medijima i fajlovima na vašem uređaju?"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"snima zvuk"</string>
- <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> snimanje zvuka?"</string>
+ <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> da snima zvuk?"</string>
<string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Fizička aktivnost"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"pristup vašoj fizičkoj aktivnosti"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"Dopustiti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> da pristupi informacijama o vašoj fizičkoj aktivnosti?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"snima fotografije i videozapise"</string>
- <string name="permgrouprequest_camera" msgid="1299833592069671756">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> snimanje fotografija i videozapisa?"</string>
+ <string name="permgrouprequest_camera" msgid="1299833592069671756">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> da snima fotografije i videozapise?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Zapisnici poziva"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"čitanje i pisanje zapisnika telefonskih poziva"</string>
- <string name="permgrouprequest_calllog" msgid="8487355309583773267">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> pristup zapisnicima poziva?"</string>
+ <string name="permgrouprequest_calllog" msgid="8487355309583773267">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> da pristupa zapisnicima poziva?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Telefon"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"poziva i upravlja pozivima"</string>
- <string name="permgrouprequest_phone" msgid="9166979577750581037">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> upućivanje poziva i upravljanje njima?"</string>
+ <string name="permgrouprequest_phone" msgid="9166979577750581037">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> da upućuje pozove i upravlja njima?"</string>
<string name="permgrouplab_sensors" msgid="4838614103153567532">"Tjelesni senzori"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"pristupa podacima senzora o vašim vitalnim funkcijama"</string>
<string name="permgrouprequest_sensors" msgid="6349806962814556786">"Dozvoliti aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> pristup senzornim podacima o vašim vitalnim znacima?"</string>
@@ -574,11 +574,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Ponovo registrirajte lice."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Nije više moguće prepoznati lice. Pokušajte opet."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Previše slično, promijenite položaj."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Gledajte direktno u ekran."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Gledajte direktno u ekran."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Poravnajte položaj glave vertikalno."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Sklonite prepreke između vaše glave i telefona."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Očistite kameru."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Malo manje zakrenite glavu."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Malo manje zakrenite glavu."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Malo manje zakrenite glavu."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Uklonite prepreke koje blokiraju vaše lice."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Očistite senzor na gornjem rubu ekrana."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nije moguće potvrditi lice. Hardver nije dostupan."</string>
@@ -1621,7 +1621,7 @@
<string name="media_route_button_content_description" msgid="591703006349356016">"Emitiranje"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"Poveži na uređaj"</string>
<string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Emitiranje ekrana na uređaj"</string>
- <string name="media_route_chooser_searching" msgid="4776236202610828706">"Traženje uređajā…"</string>
+ <string name="media_route_chooser_searching" msgid="4776236202610828706">"Traženje uređaja…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Postavke"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Prekini vezu"</string>
<string name="media_route_status_scanning" msgid="7279908761758293783">"Skeniranje…"</string>
@@ -1825,7 +1825,7 @@
<string name="package_installed_device_owner" msgid="6875717669960212648">"Instalirao je vaš administrator"</string>
<string name="package_updated_device_owner" msgid="1847154566357862089">"Ažurirao je vaš administrator"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"Izbrisao je vaš administrator"</string>
- <string name="confirm_battery_saver" msgid="639106420541753635">"UREDU"</string>
+ <string name="confirm_battery_saver" msgid="639106420541753635">"Uredu"</string>
<string name="battery_saver_description_with_learn_more" msgid="2108984221113106294">"U cilju produženja trajanja baterije, funkcija Ušteda baterije isključuje ili ograničava aktivnost u pozadini, neke vizuelne efekte i druge funkcije koje troše puno energije. "<annotation id="url">"Saznajte više"</annotation></string>
<string name="battery_saver_description" msgid="6413346684861241431">"U cilju produženja trajanja baterije, funkcija Ušteda baterije isključuje ili ograničava aktivnost u pozadini, neke vizuelne efekte i druge funkcije koje troše puno energije."</string>
<string name="data_saver_description" msgid="6015391409098303235">"Da bi se smanjio prijenos podataka, Ušteda podataka sprečava da neke aplikacije šalju ili primaju podatke u pozadini. Aplikacija koju trenutno koristite može pristupiti podacima, ali će to činiti rjeđe. To može značiti, naprimjer, da se slike ne prikazuju sve dok ih ne dodirnete."</string>
@@ -2065,4 +2065,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fajlova</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Direktno dijeljenje nije dostupno"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Spisak aplikacija"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 7b8d34c..8fe0cbc 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Torna a registrar la teva cara."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Ja no es reconeix la teva cara. Torna-ho a provar."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"És massa semblant; canvia de postura."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Mira més directament cap a la pantalla."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Mira més directament cap a la pantalla."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Mantén el cap recte, sense inclinar-lo."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Procura que no hi hagi res entre tu i el telèfon."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Neteja la càmera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Inclina el cap una mica menys."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Inclina el cap una mica menys."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"No inclinis tant el cap."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Suprimeix qualsevol cosa que amagui la teva cara."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Neteja el sensor de l\'extrem superior."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"No es pot verificar la cara. Maquinari no disponible."</string>
@@ -815,10 +815,10 @@
<string name="lockscreen_password_wrong" msgid="5737815393253165301">"Torna-ho a provar"</string>
<string name="lockscreen_storage_locked" msgid="9167551160010625200">"Desbl. per accedir a totes les funcions i dades"</string>
<string name="faceunlock_multiple_failures" msgid="754137583022792429">"S\'ha superat el nombre màxim d\'intents de desbloqueig facial"</string>
- <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"No hi ha cap targeta SIM."</string>
- <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hi ha cap targeta SIM a la tauleta."</string>
- <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"No hi ha cap targeta SIM al televisor."</string>
- <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No hi ha cap targeta SIM al telèfon."</string>
+ <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"No hi ha cap SIM"</string>
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hi ha cap SIM a la tauleta."</string>
+ <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"No hi ha cap SIM al televisor."</string>
+ <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No hi ha cap SIM al telèfon."</string>
<string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Insereix una targeta SIM."</string>
<string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"Falta la targeta SIM o no es pot llegir. Insereix-ne una."</string>
<string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"Targeta SIM no utilitzable."</string>
@@ -1595,7 +1595,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"Pantalla sense fil"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"Emet"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"Connexió al dispositiu"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Emissió de pantalla al dispositiu"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Emet pantalla al dispositiu"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"S\'estan cercant dispositius…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Configuració"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Desconnecta"</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> i <xliff:g id="COUNT_1">%d</xliff:g> fitxer més</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"No es pot compartir directament"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Llista d\'aplicacions"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 9b2b569..bd014f8 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -577,11 +577,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Zaznamenejte obličej znovu."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Obličej už nelze rozpoznat. Zkuste to znovu."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Příliš podobné, změňte výraz."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Dívejte se přímo na obrazovku."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Dívejte se přímo na obrazovku."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Narovnejte hlavu."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Mezi vaší hlavou a telefonem nesmí nic překážet."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Očistěte fotoaparát."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Natočte hlavu o něco méně."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Natočte hlavu o něco méně."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Natočte hlavu o něco méně."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Odstraňte vše, co vám zakrývá obličej."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Vyčistěte snímač u horního okraje obrazovky."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Obličej nelze ověřit. Hardware není dostupný."</string>
@@ -985,7 +985,7 @@
</plurals>
<string name="last_month" msgid="3959346739979055432">"Poslední měsíc"</string>
<string name="older" msgid="5211975022815554840">"Starší"</string>
- <string name="preposition_for_date" msgid="9093949757757445117">"dne <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"v <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"roku <xliff:g id="YEAR">%s</xliff:g>"</string>
<string name="day" msgid="8144195776058119424">"den"</string>
@@ -2099,4 +2099,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> soubor</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Přímé sdílení není k dispozici"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Seznam aplikací"</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 91db9ef..230067e 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registrer dit ansigt igen."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Ansigtet kan ikke længere genkendes. Prøv igen."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Det minder for meget om et andet. Skift stilling."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Kig mere direkte på skærmen."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Kig mere direkte på skærmen."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Hold hovedet helt lodret."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Sørg for, at der ikke er noget foran dit ansigt."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Rengør kameraet."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Sørg for, at hovedet ikke er drejet for meget."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Sørg for, at hovedet ikke er bøjet for meget."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Sørg for, at dit hoved ikke er drejet for meget."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Hvis noget skjuler dit ansigt, skal du fjerne det."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Rens sensoren ved skærmens øverste kant."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Ansigt ikke bekræftet. Hardware ikke tilgængelig."</string>
@@ -1595,7 +1595,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"Trådløs skærm"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"Cast"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"Opret forbindelse til enheden"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Send skærm til enhed"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Cast skærm til enhed"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"Søger efter enheder…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Indstillinger"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Afbryd forbindelsen"</string>
@@ -1649,9 +1649,9 @@
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Du har forsøgt at låse tabletten op forkert <xliff:g id="NUMBER">%d</xliff:g> gange. Tabletten nulstilles til fabriksindstillingerne."</string>
<string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Du har forsøgt at låse tv\'et forkert op <xliff:g id="NUMBER">%d</xliff:g> gange. Fjernsynet nulstilles nu til fabriksindstillingerne."</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Du har forsøgt at låse telefonen op forkert <xliff:g id="NUMBER">%d</xliff:g> gange. Telefonen nulstilles til fabriksindstillingerne."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%2$d</xliff:g> yderligere mislykkede forsøg vil du blive bedt om at låse din tablet op ved hjælp af en e-mailkonto\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykket forsøg bliver du bedt om at låse op for dit tv ved hjælp af en e-mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%2$d</xliff:g> yderligere mislykkede forsøg til vil du blive bedt om at låse din telefon op ved hjælp af en e-mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%2$d</xliff:g> yderligere mislykkede forsøg vil du blive bedt om at låse din tablet op ved hjælp af en mailkonto\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykket forsøg bliver du bedt om at låse op for dit tv ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%2$d</xliff:g> yderligere mislykkede forsøg til vil du blive bedt om at låse din telefon op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Fjern"</string>
<string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Vil du skrue højere op end det anbefalede lydstyrkeniveau?\n\nDu kan skade hørelsen ved at lytte til meget høj musik over længere tid."</string>
@@ -2027,4 +2027,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> filer</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Det er ikke muligt at dele direkte"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Liste over apps"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 9ff6cbf..1a94f73 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -99,7 +99,7 @@
<string name="peerTtyModeHco" msgid="5728602160669216784">"Peer hat TTY-Modus \"HCO\" angefordert."</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"Peer hat TTY-Modus \"VC\" angefordert."</string>
<string name="peerTtyModeOff" msgid="3280819717850602205">"Peer hat TTY-Modus \"Aus\" angefordert."</string>
- <string name="serviceClassVoice" msgid="1258393812335258019">"Stimme"</string>
+ <string name="serviceClassVoice" msgid="1258393812335258019">"Sprache"</string>
<string name="serviceClassData" msgid="872456782077937893">"Daten"</string>
<string name="serviceClassFAX" msgid="5566624998840486475">"FAX"</string>
<string name="serviceClassSMS" msgid="2015460373701527489">"SMS"</string>
@@ -554,8 +554,8 @@
<string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"Gesichtserkennungshardware verwenden"</string>
<string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Ermöglicht der App, für die Authentifizierung Gesichtserkennungshardware zu verwenden"</string>
<string name="face_recalibrate_notification_name" msgid="3976629945250435054">"Gesichtserkennung"</string>
- <string name="face_recalibrate_notification_title" msgid="4087620069451499365">"Gesicht neu scannen"</string>
- <string name="face_recalibrate_notification_content" msgid="5530308842361499835">"Für bessere Erkennung Gesicht neu scannen"</string>
+ <string name="face_recalibrate_notification_title" msgid="4087620069451499365">"Gesicht neu scannen lassen"</string>
+ <string name="face_recalibrate_notification_content" msgid="5530308842361499835">"Für bessere Erkennung Gesicht neu scannen lassen"</string>
<string name="face_acquired_insufficient" msgid="2767330364802375742">"Gesichtsdaten nicht gut erfasst. Erneut versuchen."</string>
<string name="face_acquired_too_bright" msgid="5005650874582450967">"Zu hell. Schwächere Beleuchtung ausprobieren."</string>
<string name="face_acquired_too_dark" msgid="1966194696381394616">"Zu dunkel. Probier eine hellere Beleuchtung aus."</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Bitte registriere dein Gesicht noch einmal."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Gesicht wird nicht mehr erkannt. Erneut versuchen."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Zu ähnlich. Bitte dreh deinen Kopf etwas."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Bitte sieh direkt auf das Display."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Bitte sieh direkt auf das Display."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Bitte halte deinen Kopf gerade."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Halte den Platz zwischen Kopf und Smartphone frei."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Bitte reinige die Kamera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Dreh den Kopf etwas weniger zur Seite."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Neig den Kopf etwas weniger stark."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Neig den Kopf etwas weniger stark."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Entferne alles, was dein Gesicht verdeckt."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Reinige den Sensor am oberen Rand des Bildschirms."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Gesicht nicht erkannt. Hardware nicht verfügbar."</string>
@@ -1180,7 +1180,7 @@
<string name="unsupported_display_size_show" msgid="7969129195360353041">"Immer anzeigen"</string>
<string name="unsupported_compile_sdk_message" msgid="4253168368781441759">"<xliff:g id="APP_NAME">%1$s</xliff:g> ist mit der Version deines Android-Betriebssystems nicht kompatibel, wodurch ein unerwartetes Verhalten auftreten kann. Möglicherweise ist eine aktualisierte Version der App verfügbar."</string>
<string name="unsupported_compile_sdk_show" msgid="2681877855260970231">"Immer anzeigen"</string>
- <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Auf Updates überprüfen"</string>
+ <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Auf Updates prüfen"</string>
<string name="smv_application" msgid="3307209192155442829">"Die App <xliff:g id="APPLICATION">%1$s</xliff:g> (Prozess <xliff:g id="PROCESS">%2$s</xliff:g>) hat gegen deine selbsterzwungene StrictMode-Richtlinie verstoßen."</string>
<string name="smv_process" msgid="5120397012047462446">"Der Prozess <xliff:g id="PROCESS">%1$s</xliff:g> hat gegen seine selbsterzwungene StrictMode-Richtlinie verstoßen."</string>
<string name="android_upgrading_title" product="default" msgid="7513829952443484438">"Smartphone wird aktualisiert…"</string>
@@ -1364,7 +1364,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"TEILEN"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ABLEHNEN"</string>
<string name="select_input_method" msgid="4653387336791222978">"Eingabemethode wählen"</string>
- <string name="show_ime" msgid="2506087537466597099">"Auf dem Display einblenden, wenn die physische Tastatur aktiv ist"</string>
+ <string name="show_ime" msgid="2506087537466597099">"Bildschirmtastatur auch dann anzeigen, wenn physische Tastatur aktiv ist"</string>
<string name="hardware" msgid="194658061510127999">"Virtuelle Tastatur einblenden"</string>
<string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Physische Tastatur konfigurieren"</string>
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Zum Auswählen von Sprache und Layout tippen"</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> und <xliff:g id="COUNT_1">%d</xliff:g> Datei</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Direct Share nicht verfügbar"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Liste der Apps"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index cdd14d1..fac3a62 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Καταχωρίστε ξανά το πρόσωπό σας."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Αδύνατη η αναγνώριση του προσώπου. Επανάληψη."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Πολύ παρόμοιο, αλλάξτε την πόζα σας."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Κοιτάξτε απευθείας στην οθόνη."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Κοιτάξτε απευθείας στην οθόνη."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Ευθυγραμμίστε το κεφάλι σας στον κατακόρυφο άξονα."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Αδειάστε τον χώρο ανάμεσα σε εσάς και το τηλέφωνο."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Καθαρίστε την κάμερα."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Στρέψτε λιγότερο το κεφάλι σας."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Στρέψτε λιγότερο το κεφάλι σας."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Στρέψτε λιγότερο το κεφάλι σας."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Απομακρύνετε οτιδήποτε κρύβει το πρόσωπό σας."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Καθαρίστε τον αισθητήρα επάνω στην οθόνη."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Αδύν. επαλήθ. προσώπου. Μη διαθέσιμος εξοπλισμός."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> αρχείο</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Η άμεση κοινοποίηση δεν είναι διαθέσιμη"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Λίστα εφαρμογών"</string>
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 12d633c..ef92758 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -272,7 +272,7 @@
<string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tap for details on battery and data usage"</string>
<string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
- <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
+ <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
<string name="user_owner_label" msgid="8836124313744349203">"Switch to personal profile"</string>
<string name="managed_profile_label" msgid="8947929265267690522">"Switch to work profile"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
@@ -303,7 +303,7 @@
<string name="permgroupdesc_camera" msgid="3250611594678347720">"take pictures and record video"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to take pictures and record video?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Call logs"</string>
- <string name="permgroupdesc_calllog" msgid="3006237336748283775">"read and write phone call log"</string>
+ <string name="permgroupdesc_calllog" msgid="3006237336748283775">"read and write phone call logs"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to access your phone call logs?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Telephone"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"make and manage phone calls"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Please re-enroll your face."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"No longer able to recognise face. Try again."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Too similar, please change your pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Please look more directly at the screen."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Please look more directly at the screen."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Please straighten your head vertically."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Clear the space between your head and the phone."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Please clean the camera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Turn your head a little less."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Turn your head a little less."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Turn your head a little less."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Remove anything hiding your face."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Clean the sensor at the top edge of the screen."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Can’t verify face. Hardware not available."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> file</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Direct share not available"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Apps list"</string>
</resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 065d845..eb2b012 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -272,7 +272,7 @@
<string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tap for details on battery and data usage"</string>
<string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
- <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
+ <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
<string name="user_owner_label" msgid="8836124313744349203">"Switch to personal profile"</string>
<string name="managed_profile_label" msgid="8947929265267690522">"Switch to work profile"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
@@ -303,7 +303,7 @@
<string name="permgroupdesc_camera" msgid="3250611594678347720">"take pictures and record video"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to take pictures and record video?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Call logs"</string>
- <string name="permgroupdesc_calllog" msgid="3006237336748283775">"read and write phone call log"</string>
+ <string name="permgroupdesc_calllog" msgid="3006237336748283775">"read and write phone call logs"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to access your phone call logs?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Telephone"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"make and manage phone calls"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Please re-enroll your face."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"No longer able to recognise face. Try again."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Too similar, please change your pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Please look more directly at the screen."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Please look more directly at the screen."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Please straighten your head vertically."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Clear the space between your head and the phone."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Please clean the camera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Turn your head a little less."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Turn your head a little less."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Turn your head a little less."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Remove anything hiding your face."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Clean the sensor at the top edge of the screen."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Can’t verify face. Hardware not available."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> file</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Direct share not available"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Apps list"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 12d633c..ef92758 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -272,7 +272,7 @@
<string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tap for details on battery and data usage"</string>
<string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
- <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
+ <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
<string name="user_owner_label" msgid="8836124313744349203">"Switch to personal profile"</string>
<string name="managed_profile_label" msgid="8947929265267690522">"Switch to work profile"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
@@ -303,7 +303,7 @@
<string name="permgroupdesc_camera" msgid="3250611594678347720">"take pictures and record video"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to take pictures and record video?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Call logs"</string>
- <string name="permgroupdesc_calllog" msgid="3006237336748283775">"read and write phone call log"</string>
+ <string name="permgroupdesc_calllog" msgid="3006237336748283775">"read and write phone call logs"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to access your phone call logs?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Telephone"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"make and manage phone calls"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Please re-enroll your face."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"No longer able to recognise face. Try again."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Too similar, please change your pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Please look more directly at the screen."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Please look more directly at the screen."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Please straighten your head vertically."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Clear the space between your head and the phone."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Please clean the camera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Turn your head a little less."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Turn your head a little less."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Turn your head a little less."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Remove anything hiding your face."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Clean the sensor at the top edge of the screen."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Can’t verify face. Hardware not available."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> file</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Direct share not available"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Apps list"</string>
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 12d633c..ef92758 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -272,7 +272,7 @@
<string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tap for details on battery and data usage"</string>
<string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
- <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
+ <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
<string name="user_owner_label" msgid="8836124313744349203">"Switch to personal profile"</string>
<string name="managed_profile_label" msgid="8947929265267690522">"Switch to work profile"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
@@ -303,7 +303,7 @@
<string name="permgroupdesc_camera" msgid="3250611594678347720">"take pictures and record video"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to take pictures and record video?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Call logs"</string>
- <string name="permgroupdesc_calllog" msgid="3006237336748283775">"read and write phone call log"</string>
+ <string name="permgroupdesc_calllog" msgid="3006237336748283775">"read and write phone call logs"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to access your phone call logs?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Telephone"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"make and manage phone calls"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Please re-enroll your face."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"No longer able to recognise face. Try again."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Too similar, please change your pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Please look more directly at the screen."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Please look more directly at the screen."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Please straighten your head vertically."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Clear the space between your head and the phone."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Please clean the camera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Turn your head a little less."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Turn your head a little less."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Turn your head a little less."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Remove anything hiding your face."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Clean the sensor at the top edge of the screen."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Can’t verify face. Hardware not available."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> file</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Direct share not available"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Apps list"</string>
</resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index fbe82b7..53b3c2c 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Please re-enroll your face."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"No longer able to recognize face. Try again."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Too similar, please change your pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Please look more directly at the screen."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Please look more directly at the screen."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Please straighten your head vertically."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Clear the space between your head and the phone."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Please clean the camera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Turn your head a little less."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Turn your head a little less."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Turn your head a little less."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Remove anything hiding your face."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Clean the sensor at the top edge of the screen."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Can’t verify face. Hardware not available."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> file</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Direct share not available"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Apps list"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index d9cb0c7..ead403f 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -302,7 +302,7 @@
<string name="permgrouplab_camera" msgid="4820372495894586615">"Cámara"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"tomar fotografías y grabar videos"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"¿Permitir que <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> tome fotos y grabe videos?"</string>
- <string name="permgrouplab_calllog" msgid="8798646184930388160">"Registro de llamadas"</string>
+ <string name="permgrouplab_calllog" msgid="8798646184930388160">"Llamadas"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"leer y escribir el registro de llamadas telefónicas"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"¿Permitir que <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda al registro de las llamadas telefónicas?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Teléfono"</string>
@@ -402,7 +402,7 @@
<string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Permite que la aplicación modifique el registro de llamadas de la TV, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden usar este permiso para borrar o modificar el registro de llamadas."</string>
<string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Permite que la aplicación modifique el registro de llamadas del dispositivo, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden usar este permiso para borrar o modificar el registro de llamadas."</string>
<string name="permlab_bodySensors" msgid="4683341291818520277">"acceder a los sensores corporales (como los monitores de frecuencia cardíaca)"</string>
- <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite que la app acceda a datos de sensores que monitorean tu estado físico, como el ritmo cardíaco."</string>
+ <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite que la app acceda a datos de sensores que monitorean tu estado físico, como la frecuencia cardíaca."</string>
<string name="permlab_readCalendar" msgid="6716116972752441641">"Leer eventos y detalles del calendario"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"Esta app puede leer todos los eventos del calendario de tu tablet y compartir o guardar los datos correspondientes."</string>
<string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"Esta app puede leer todos los eventos del calendario de tu TV y compartir o guardar los datos correspondientes."</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Vuelve a registrar tu cara."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Ya no se reconoce la cara. Vuelve a intentarlo."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Es muy similar a la anterior. Haz otra pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Mira directamente a la pantalla."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Mira directamente a la pantalla."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Mantén la cabeza en posición vertical."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Ilumina el espacio entre tu cabeza y el teléfono."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Limpia la cámara."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Gira la cabeza un poco menos."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Gira la cabeza un poco menos."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Gira la cabeza un poco menos."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Quítate cualquier objeto que te cubra el rostro."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpiar sensor del borde superior de la pantalla."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"No se verificó el rostro. Hardware no disponible."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> y <xliff:g id="COUNT_1">%d</xliff:g> archivo más</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"No está disponible el uso compartido directo"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lista de apps"</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 8a0f34b..17e7c4a 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Vuelve a registrar tu cara."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"No puede reconocer tu cara. Vuelve a intentarlo."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Se parece mucha a la anterior. Pon otra cara."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Mira más fijamente a la pantalla."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Mira más fijamente a la pantalla."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Mantén la cabeza en posición vertical."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"No dejes espacio entre tu cabeza y el teléfono."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Limpia la cámara."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Gira la cabeza un poco menos."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Gira la cabeza un poco menos."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"No gires tanto la cabeza."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Retira cualquier objeto que no deje ver tu cara."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpia el sensor situado en la parte superior."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"No se puede verificar. Hardware no disponible."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> y <xliff:g id="COUNT_1">%d</xliff:g> archivo</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"No se puede compartir directamente"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lista de aplicaciones"</string>
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 6ac6c2e..84500af 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registreerige oma nägu uuesti."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Nägu ei õnnestu enam tuvastada. Proovige uuesti."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Liiga sarnane, palun muutke oma asendit."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Vaadake otse ekraanile."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Vaadake otse ekraanile."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Pange pea vertikaalselt otseks."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Eemaldage pea ja telefoni vahelt takistused."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Puhastage kaamerat."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Pöörake oma pead veidi vähem."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Pöörake oma pead veidi vähem."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Pöörake oma pead veidi vähem."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Eemaldage kõik, mis varjab teie nägu."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Puhastage ekraani ülaservas olev andur."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nägu ei saa kinnitada. Riistvara pole saadaval."</string>
@@ -1801,7 +1801,7 @@
<string name="confirm_battery_saver" msgid="639106420541753635">"OK"</string>
<string name="battery_saver_description_with_learn_more" msgid="2108984221113106294">"Aku tööea pikendamiseks lülitab akusäästja taustategevused, mõningad visuaalsed efektid ja muud akut koormavad funktsioonid välja või piirab neid. "<annotation id="url">"Lisateave"</annotation></string>
<string name="battery_saver_description" msgid="6413346684861241431">"Aku tööea pikendamiseks lülitab akusäästja taustategevused, mõningad visuaalsed efektid ja muud akut koormavad funktsioonid välja või piirab neid."</string>
- <string name="data_saver_description" msgid="6015391409098303235">"Andmekasutuse vähendamiseks keelab andmemahu säästja mõne rakenduse puhul andmete taustal saatmise ja vastuvõtmise. Rakendus, mida praegu kasutate, pääseb andmesidele juurde, kuid võib seda teha väiksema sagedusega. Seetõttu võidakse näiteks kujutised kuvada alles siis, kui neid puudutate."</string>
+ <string name="data_saver_description" msgid="6015391409098303235">"Andmekasutuse vähendamiseks keelab andmemahu säästja mõne rakenduse puhul andmete taustal saatmise ja vastuvõtmise. Rakendus, mida praegu kasutate, pääseb andmesidele juurde, kuid võib seda teha väiksema sagedusega. Seetõttu võidakse näiteks pildid kuvada alles siis, kui neid puudutate."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Lül. andmemahu säästja sisse?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"Lülita sisse"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> fail</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Vahetu jagamine ei ole saadaval"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Rakenduste loend"</string>
</resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 1437fa5..8b6a5f8 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -328,7 +328,7 @@
<string name="permlab_statusBarService" msgid="4826835508226139688">"bihurtu egoera-barra"</string>
<string name="permdesc_statusBarService" msgid="716113660795976060">"Egoera-barra izatea baimentzen die aplikazioei."</string>
<string name="permlab_expandStatusBar" msgid="1148198785937489264">"zabaldu/tolestu egoera-barra"</string>
- <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Egoera-barra zabaltzea edo tolestea baimentzen die aplikazioei."</string>
+ <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Egoera-barra zabaltzeko edo tolesteko aukera ematen die aplikazioei."</string>
<string name="permlab_install_shortcut" msgid="4279070216371564234">"instalatu lasterbideak"</string>
<string name="permdesc_install_shortcut" msgid="8341295916286736996">"Erabiltzaileak ezer egin gabe hasierako pantailan lasterbideak gehitzeko aukera ematen die aplikazioei."</string>
<string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"desinstalatu lasterbideak"</string>
@@ -344,7 +344,7 @@
<string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"irakurri sare mugikor bidezko igorpen-mezuak"</string>
<string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Gailuak jasotako sare mugikor bidezko igorpenen mezuak irakurtzeko baimena ematen die aplikazioei. Sare mugikor bidezko igorpen-alertak kokapen batzuetan ematen dira larrialdi-egoeren berri emateko. Aplikazio gaiztoek gailuaren errendimendua edo funtzionamendua oztopa dezakete larrialdi-igorpen horietako bat jasotzen denean."</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"irakurri harpidetutako jarioak"</string>
- <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Unean sinkronizatutako jarioei buruzko xehetasunak lortzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Unean sinkronizatutako jarioei buruzko xehetasunak lortzeko baimena ematen die aplikazioei."</string>
<string name="permlab_sendSms" msgid="7544599214260982981">"bidali eta ikusi SMS mezuak"</string>
<string name="permdesc_sendSms" msgid="7094729298204937667">"SMS mezuak bidaltzeko baimena ematen die aplikazioei. Horrela, ustekabeko gastuak eragin daitezke. Aplikazio gaiztoek erabil dezakete zuk berretsi gabeko mezuak bidalita gastuak eragiteko."</string>
<string name="permlab_readSms" msgid="8745086572213270480">"irakurri testu-mezuak (SMSak edo MMSak)"</string>
@@ -376,13 +376,13 @@
<string name="permlab_foregroundService" msgid="3310786367649133115">"Exekutatu zerbitzuak aurreko planoan"</string>
<string name="permdesc_foregroundService" msgid="6471634326171344622">"Aurreko planoko zerbitzuak erabiltzea baimentzen dio aplikazioari."</string>
<string name="permlab_getPackageSize" msgid="7472921768357981986">"neurtu aplikazioen biltegiratzeko tokia"</string>
- <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Bere kodea, datuak eta cache-tamainak eskuratzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Bere kodea, datuak eta cache-tamainak eskuratzeko baimena ematen die aplikazioei."</string>
<string name="permlab_writeSettings" msgid="2226195290955224730">"aldatu sistemaren ezarpenak"</string>
- <string name="permdesc_writeSettings" msgid="7775723441558907181">"Sistemaren ezarpenen datuak aldatzea baimentzen die aplikazioei. Aplikazio gaiztoek sistemaren konfigurazioa hondatzeko erabil dezakete."</string>
+ <string name="permdesc_writeSettings" msgid="7775723441558907181">"Sistemaren ezarpenen datuak aldatzeko baimena ematen die aplikazioei. Aplikazio gaiztoek sistemaren konfigurazioa hondatzeko erabil dezakete."</string>
<string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"exekutatu abiaraztean"</string>
- <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Sistema berrabiarazi bezain laster abiaraztea baimentzen die aplikazioei. Horrela, agian denbora gehiago beharko du tabletak abiarazteko, eta tabletaren funtzionamendu orokorra mantso daiteke, baimen hori duten aplikazioak beti abian egongo baitira."</string>
- <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"Sistema berrabiarazi bezain laster abiaraztea baimentzen die aplikazioei. Horrela, telebistak denbora gehiago behar izan lezake abiarazteko, eta telebistaren funtzionamendu orokorra motel liteke, baimen hori duten aplikazioak beti abian egongo baitira."</string>
- <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Sistema berrabiarazi bezain laster abiaraztea baimentzen die aplikazioei. Horrela, agian denbora gehiago beharko du telefonoak abiarazteko, eta telefonoaren funtzionamendu orokorra mantso daiteke, baimen hori duten aplikazioak beti abian egongo baitira."</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Sistema berrabiarazi bezain laster abiarazteko baimena ematen die aplikazioei. Horrela, agian denbora gehiago beharko du tabletak abiarazteko, eta tabletaren funtzionamendu orokorra mantso daiteke, baimen hori duten aplikazioak beti abian egongo baitira."</string>
+ <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"Sistema berrabiarazi bezain laster abiarazteko baimena ematen die aplikazioei. Horrela, telebistak denbora gehiago behar izan lezake abiarazteko, eta telebistaren funtzionamendu orokorra motel liteke, baimen hori duten aplikazioak beti abian egongo baitira."</string>
+ <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Sistema berrabiarazi bezain laster abiarazteko baimena ematen die aplikazioei. Horrela, agian denbora gehiago beharko du telefonoak abiarazteko, eta telefonoaren funtzionamendu orokorra mantso daiteke, baimen hori duten aplikazioak beti abian egongo baitira."</string>
<string name="permlab_broadcastSticky" msgid="7919126372606881614">"bidali igorpen erakargarria"</string>
<string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Igorpen iraunkorrak emateko baimena ematen die; horiek igorpena amaitu ondoren mantentzen dira. Gehiegi erabiliz gero, tableta motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string>
<string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"Igorpen iraunkorrak egitea baimentzen die aplikazioei. Igorpena eten ondoren ere igortzen jarraitzen duten igorpenak dira igorpen iraunkorrak. Gehiegi erabiliz gero, telebista motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string>
@@ -393,13 +393,13 @@
<string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Telefonoan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen die aplikazioei, besteak beste, pertsona zehatzei zer maiztasunekin deitu diezun, mezu elektronikoak bidali dizkiezun edo haiekin harremanetan beste modutara nola jarri zaren. Baimen horrekin, aplikazioek kontaktuen datuak gorde ditzakete, eta aplikazio gaiztoek haiek parteka ditzakete zuk jakin gabe."</string>
<string name="permlab_writeContacts" msgid="5107492086416793544">"aldatu kontaktuak"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Tabletan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei, besteak beste, kontatu zehatzei zer maiztasunekin deitu diezun, mezu elektronikoak bidali dizkiezun edo haiekin harremanetan beste modutara nola jarri zaren. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Telebistan gordetako kontaktuei buruzko datuak aldatzea baimentzen die aplikazioei, besteak beste, kontaktu zehatzei zer maiztasunekin deitu diezun, mezu elektronikoak bidali dizkiezun ala ez, edo haiekin harremanetan zer beste modutara jarri zaren. Baimen horrekin, kontaktuen datuak ezaba ditzakete aplikazioek."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Telebistan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei, besteak beste, kontaktu zehatzei zer maiztasunekin deitu diezun, mezu elektronikoak bidali dizkiezun ala ez, edo haiekin harremanetan zer beste modutara jarri zaren. Baimen horrekin, kontaktuen datuak ezaba ditzakete aplikazioek."</string>
<string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Telefonoan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei, besteak beste, kontatu zehatzei zer maiztasunekin deitu diezun, mezu elektronikoak bidali dizkiezun edo haiekin harremanetan beste modutara nola jarri zaren. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"irakurri deien erregistroa"</string>
<string name="permdesc_readCallLog" msgid="3204122446463552146">"Aplikazioak deien historia irakur dezake."</string>
<string name="permlab_writeCallLog" msgid="8552045664743499354">"idatzi deien erregistroan"</string>
<string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Tabletaren deien erregistroa aldatzeko baimena ematen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Aplikazio gaiztoek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete."</string>
- <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Telebistako deien erregistroa aldatzea baimentzen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Aplikazio gaiztoek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete."</string>
+ <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Telebistako deien erregistroa aldatzeko baimena ematen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Aplikazio gaiztoek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete."</string>
<string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Telefonoaren deien erregistroa aldatzeko baimena ematen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Aplikazio gaiztoek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete."</string>
<string name="permlab_bodySensors" msgid="4683341291818520277">"Atzitu gorputzaren sentsoreak (adibidez, bihotz-maiztasunarenak)"</string>
<string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Zure egoera fisikoa kontrolatzen duten sentsoreetako datuak (adibidez, bihotz-maiztasuna) atzitzeko baimena ematen die aplikazioei."</string>
@@ -432,7 +432,7 @@
<string name="permlab_camera" msgid="3616391919559751192">"atera argazkiak eta grabatu bideoak"</string>
<string name="permdesc_camera" msgid="5392231870049240670">"Aplikazioak edonoiz erabil dezake kamera argazkiak ateratzeko eta bideoak grabatzeko."</string>
<string name="permlab_vibrate" msgid="7696427026057705834">"kontrolatu dardara"</string>
- <string name="permdesc_vibrate" msgid="6284989245902300945">"Bibragailua kontrolatzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_vibrate" msgid="6284989245902300945">"Bibragailua kontrolatzeko aukera ematen die aplikazioei."</string>
<string name="permlab_callPhone" msgid="3925836347681847954">"deitu zuzenean telefono-zenbakietara"</string>
<string name="permdesc_callPhone" msgid="3740797576113760827">"Telefono-zenbakietara zuk esku hartu gabe deitzeko baimena ematen die aplikazioei. Horrela, ustekabeko gastuak edo deiak eragin daitezke. Aplikazio gaiztoek erabil dezakete zuk berretsi gabeko deiak eginda gastuak eragiteko."</string>
<string name="permlab_accessImsCallService" msgid="3574943847181793918">"atzitu IMS dei-zerbitzua"</string>
@@ -458,32 +458,32 @@
<string name="permdesc_transmitIr" product="tv" msgid="3926790828514867101">"Telebistaren infragorri-igorlea erabiltzeko baimena ematen die aplikazioei."</string>
<string name="permdesc_transmitIr" product="default" msgid="7957763745020300725">"Telefonoaren infragorri-igorlea erabiltzeko aukera ematen die aplikazioei."</string>
<string name="permlab_setWallpaper" msgid="6627192333373465143">"ezarri horma-papera"</string>
- <string name="permdesc_setWallpaper" msgid="7373447920977624745">"Sistemaren horma-papera aldatzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_setWallpaper" msgid="7373447920977624745">"Sistemaren horma-papera aldatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_setWallpaperHints" msgid="3278608165977736538">"doitu horma-paperaren tamaina"</string>
<string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"Sistemaren horma-paperaren tamainaren doitzeak ezartzea baimentzen die aplikazioei."</string>
<string name="permlab_setTimeZone" msgid="2945079801013077340">"ezarri ordu-zona"</string>
- <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"Tabletaren ordu-zona aldatzea baimentzen die aplikazioei."</string>
- <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"Telebistaren ordu-zona aldatzea baimentzen die aplikazioei."</string>
- <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Telefonoaren ordu-zona aldatzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"Tabletaren ordu-zona aldatzeko baimena ematen die aplikazioei."</string>
+ <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"Telebistaren ordu-zona aldatzeko baimena ematen die aplikazioei."</string>
+ <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Telefonoaren ordu-zona aldatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_getAccounts" msgid="1086795467760122114">"bilatu gailuko kontuak"</string>
<string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Tabletak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak har daitezke barnean."</string>
- <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"Telebistak ezagutzen dituen kontuen zerrenda lortzea baimentzen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak sar daitezke."</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"Telebistak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak sar daitezke."</string>
<string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak har daitezke barnean."</string>
<string name="permlab_accessNetworkState" msgid="4951027964348974773">"ikusi sareko konexioak"</string>
<string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Sareko konexioei buruzko informazioa ikusteko baimena ematen die aplikazioei; adibidez, zer sare dauden eta zeintzuk dauden konektatuta."</string>
<string name="permlab_createNetworkSockets" msgid="7934516631384168107">"izan sarerako sarbide osoa"</string>
<string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Sare-socketak sortzeko eta sare-protokolo pertsonalizatuak erabiltzeko baimena ematen die aplikazioei. Arakatzaileak eta beste aplikazio batzuek Internetera konektatzeko moduak eskaintzen dituzte, beraz, baimen hori ez da beharrezkoa datuak Internetera bidaltzeko."</string>
<string name="permlab_changeNetworkState" msgid="958884291454327309">"aldatu sarearen konektagarritasuna"</string>
- <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Sarearen konexioaren egoera aldatzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Sarearen konexioaren egoera aldatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_changeTetherState" msgid="5952584964373017960">"aldatu telefono bidezko konektagarritasuna"</string>
- <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Partekatutako Interneterako konexioaren egoera aldatzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Partekatutako Interneterako konexioaren egoera aldatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_accessWifiState" msgid="5202012949247040011">"ikusi Wi-Fi konexioak"</string>
<string name="permdesc_accessWifiState" msgid="5002798077387803726">"Wi-Fi sareei buruzko informazioa ikusteko baimena ematen die aplikazioei, adibidez, Wi-Fi konexioa aktibatuta dagoen eta konektatutako Wi-Fi gailuen izenak zein diren."</string>
<string name="permlab_changeWifiState" msgid="6550641188749128035">"konektatu Wi-Fira edo deskonektatu bertatik"</string>
<string name="permdesc_changeWifiState" msgid="7137950297386127533">"Wi-Fi sarbide-puntuetara konektatzeko edo haietatik deskonektatzeko baimena ematen die aplikazioei, baita Wi-Fi sareen gailu-konfigurazioari aldaketak egitekoa ere."</string>
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"onartu Wi-Fi Multicast harrera"</string>
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Wi-Fi sarearen bidez gailu guztiei bidalitako paketeak jasotzeko baimena ematen die aplikazioei multidifusio-helbideak erabilita, ez tableta soilik. Multidifusiokoa ez den moduak baino bateria gehiago erabiltzen du."</string>
- <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"Wi-Fi sareko gailu guztiei bidalitako paketeak jasotzea baimentzen die aplikazioei multidifusio-helbideak erabilita, ez telebista soilik. Multidifusiokoa ez den moduak baino bateria gehiago erabiltzen du."</string>
+ <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"Wi-Fi sareko gailu guztiei bidalitako paketeak jasotzeko baimena ematen die aplikazioei multidifusio-helbideak erabilita, ez telebista soilik. Multidifusiokoa ez den moduak baino bateria gehiago erabiltzen du."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Wi-Fi sarearen bidez gailu guztiei bidalitako paketeak jasotzeko baimena ematen die aplikazioei multidifusio-helbideak erabilita, ez telefonoa soilik. Multidifusiokoa ez den moduak baino bateria gehiago erabiltzen du."</string>
<string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"atzitu Bluetooth ezarpenak"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Tokiko Bluetooth tableta konfiguratzea eta urruneko gailuak detektatzea eta haiekin parekatzea baimentzen die aplikazioei."</string>
@@ -512,11 +512,11 @@
<string name="permlab_useFingerprint" msgid="3150478619915124905">"erabili erreferentzia-gako digitalen hardwarea"</string>
<string name="permdesc_useFingerprint" msgid="9165097460730684114">"Autentifikatzeko erreferentzia-gako digitalen hardwarea erabiltzeko baimena ematen die aplikazioei."</string>
<string name="permlab_audioWrite" msgid="2661772059799779292">"musika-bilduma aldatu"</string>
- <string name="permdesc_audioWrite" msgid="8888544708166230494">"Musika-bilduma aldatzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_audioWrite" msgid="8888544708166230494">"Musika-bilduma aldatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_videoWrite" msgid="128769316366746446">"bideo-bilduma aldatu"</string>
- <string name="permdesc_videoWrite" msgid="5448565757490640841">"Bideo-bilduma aldatzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_videoWrite" msgid="5448565757490640841">"Bideo-bilduma aldatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_imagesWrite" msgid="3391306186247235510">"argazki-bilduma aldatu"</string>
- <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Argazki-bilduma aldatzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Argazki-bilduma aldatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_mediaLocation" msgid="8675148183726247864">"multimedia-edukien bildumako kokapena irakurri"</string>
<string name="permdesc_mediaLocation" msgid="2237023389178865130">"Multimedia-edukien bildumako kokapena irakurtzeko baimena ematen die aplikazioei."</string>
<string name="biometric_dialog_default_title" msgid="881952973720613213">"Egiaztatu zeu zarela"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Erregistratu berriro aurpegia."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Ez dugu ezagutzen aurpegi hori. Saiatu berriro."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Jarrera berdintsuegia da. Alda ezazu."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Begiratu zuzenago pantailari."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Begiratu zuzenago pantailari."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Jarri burua zuzen."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Kendu buruaren eta telefonoaren arteko oztopoak."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Garbitu kamera"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Biratu burua pixka bat gutxiago."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Biratu burua pixka bat gutxiago."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Biratu burua pixka bat gutxiago."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Kendu aurpegia estaltzen dizuten gauzak."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Garbitu pantailaren goiko ertzeko sentsorea."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Ezin da egiaztatu aurpegia. Hardwarea ez dago erabilgarri."</string>
@@ -603,7 +603,7 @@
<string name="permlab_sdcardWrite" msgid="9220937740184960897">"Aldatu edo ezabatu biltegiratze partekatuko edukia"</string>
<string name="permdesc_sdcardWrite" msgid="2834431057338203959">"Biltegiratze partekatuko edukian idazteko baimena ematen die aplikazioei."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"egin/jaso SIP deiak"</string>
- <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP deiak egitea eta jasotzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP deiak egitea eta jasotzeko baimena ematen die aplikazioei."</string>
<string name="permlab_register_sim_subscription" msgid="3166535485877549177">"erregistratu telekomunikabideekiko SIM konexio berriak"</string>
<string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"Telekomunikabideekiko SIM konexio berriak erregistratzea baimentzen die aplikazioei."</string>
<string name="permlab_register_call_provider" msgid="108102120289029841">"erregistratu telekomunikabideekiko konexio berriak"</string>
@@ -611,7 +611,7 @@
<string name="permlab_connection_manager" msgid="1116193254522105375">"kudeatu telekomunikabideekiko konexioak"</string>
<string name="permdesc_connection_manager" msgid="5925480810356483565">"Telekomunikabideekiko konexioak kudeatzea baimentzen die aplikazioei."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"erabili pantaila deiak abian direnean"</string>
- <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Erabiltzaileak deiaren pantaila noiz eta nola ikusten duen kontrolatzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Erabiltzaileak deiaren pantaila noiz eta nola ikusten duen kontrolatzeko aukera ematen die aplikazioei."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"elkarreragin telefono-zerbitzuekin"</string>
<string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Deiak egiteko eta jasotzeko telefonia-zerbitzuekin elkarreragitea baimentzen die aplikazioei."</string>
<string name="permlab_control_incall_experience" msgid="9061024437607777619">"eskaini erabiltzaileentzako aukerak deiak abian direnean"</string>
@@ -635,11 +635,11 @@
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"hauteman sarearen baldintzei buruzko behaketak"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Sareko baldintzak hautemateko aukera ematen die aplikazioei. Aplikazio normalek ez dute baimen hau behar."</string>
<string name="permlab_setInputCalibration" msgid="4902620118878467615">"Aldatu idazteko gailuaren kalibrazioa"</string>
- <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Ukipen-pantailaren kalibrazio-parametroak aldatzea baimentzen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
+ <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Ukipen-pantailaren kalibrazio-parametroak aldatzeko baimena ematen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"atzitu DRM ziurtagiriak"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"DRM ziurtagiriak hornitzea eta erabiltzeko baimena ematen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
<string name="permlab_handoverStatus" msgid="7820353257219300883">"Jaso Android Beam transferentzien egoera"</string>
- <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Uneko Android Beam transferentziei buruzko informazioa jasotzea baimentzen die aplikazioei"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Uneko Android Beam transferentziei buruzko informazioa jasotzeko baimena ematen die aplikazioei"</string>
<string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"kendu DRM ziurtagiriak"</string>
<string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"DRM ziurtagiriak kentzea baimentzen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
<string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"lotu operadorearen mezularitza-zerbitzuari"</string>
@@ -933,14 +933,14 @@
<string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Arakatzailearen bidez bisitatutako URL guztien historia eta arakatzailearen laster-marka guztiak irakurtzeko baimena ematen die aplikazioei. Oharra: agian baimen hori ez dute aplikatuko hirugarrenen arakatzaileek edo sarea arakatzeko gaitasuna duten bestelako aplikazioek."</string>
<string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"idatzi sareko laster-marka eta historian"</string>
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Arakatzailearen historia edo tabletan gordetako laster-markak aldatzeko baimena ematen die aplikazioei. Horrela, aplikazioak agian arakatzaile-datuak ezabatu edo aldatu ahal izango ditu. Oharra: baimen hori hirugarrenen arakatzaileek edo sarea arakatzeko gaitasuna eskaintzen duten bestelako aplikazioek aplika dezakete."</string>
- <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"Arakatzailearen historia edo telebistan gordetako laster-markak aldatzea baimentzen die aplikazioei. Horrela, aplikazioek arakatzaileko datuak ezabatu edo aldatu ahal izango dituzte agian. Oharra: hirugarrenen arakatzaileek edo sarea arakatzeko gaitasuna duten bestelako aplikazioek erabil dezakete baimen hori."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"Arakatzailearen historia edo telebistan gordetako laster-markak aldatzeko baimena ematen die aplikazioei. Horrela, aplikazioek arakatzaileko datuak ezabatu edo aldatu ahal izango dituzte agian. Oharra: hirugarrenen arakatzaileek edo sarea arakatzeko gaitasuna duten bestelako aplikazioek erabil dezakete baimen hori."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Arakatzailearen historia edo telefonoan gordetako laster-markak aldatzeko baimena ematen die aplikazioei. Horrela, aplikazioak agian arakatzaile-datuak ezabatu edo aldatu ahal izango ditu. Oharra: baimen hori hirugarrenen arakatzaileek edo sarea arakatzeko gaitasuna eskaintzen duten bestelako aplikazioek aplika dezakete."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"ezarri alarmak"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Instalatutako alarma batean alarmak ezartzea baimentzen die aplikazioei. Alarma-aplikazio batzuek agian ez dute eginbide hori inplementatuko."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"gehitu erantzungailua"</string>
- <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Erantzungailuko sarrera-ontzian mezuak gehitzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Erantzungailuko sarrera-ontzian mezuak gehitzeko baimena ematen die aplikazioei."</string>
<string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"aldatu arakatzailearen geokokapenaren baimenak"</string>
- <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Arakatzailearen geokokapenaren baimenak aldatzea baimentzen die aplikazioei. Aplikazio gaiztoek hori erabil dezakete kokapenari buruzko informazioa haiek hautatutako webguneetara bidaltzeko."</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Arakatzailearen geokokapenaren baimenak aldatzeko baimena ematen die aplikazioei. Aplikazio gaiztoek hori erabil dezakete kokapenari buruzko informazioa haiek hautatutako webguneetara bidaltzeko."</string>
<string name="save_password_message" msgid="767344687139195790">"Arakatzaileak pasahitza gogoratzea nahi duzu?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ez une honetan"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Gogoratu"</string>
@@ -1353,7 +1353,7 @@
<string name="adb_active_notification_message" msgid="7463062450474107752">"Sakatu USB arazketa desaktibatzeko"</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Hautatu USB arazketa desgaitzeko."</string>
<string name="test_harness_mode_notification_title" msgid="2216359742631914387">"Proba-materialeko modua gaitu da"</string>
- <string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Proba-materialaren modua desgaitzeko, berrezarri jatorrizko ezarpenak."</string>
+ <string name="test_harness_mode_notification_message" msgid="1343197173054407119">"Proba-materialaren modua desgaitzeko, berrezarri jatorrizko datuak."</string>
<string name="usb_contaminant_detected_title" msgid="7136400633704058349">"Likidoa edo zikinkeriak daude USB atakan"</string>
<string name="usb_contaminant_detected_message" msgid="832337061059487250">"USB ataka automatikoki desgaitu da. Informazio gehiago lortzeko, sakatu hau."</string>
<string name="usb_contaminant_not_detected_title" msgid="4202417484434906086">"Segurtasunez erabil daiteke USB ataka"</string>
@@ -2028,4 +2028,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> fitxategi</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Zuzenean partekatzeko aukera ez dago erabilgarri"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Aplikazioen zerrenda"</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 406fd1b..3c14011 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -304,7 +304,7 @@
<string name="permgrouprequest_camera" msgid="1299833592069671756">"به <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> اجازه داده شود عکس بگیرد و ویدیو ضبط کند؟"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"گزارشهای تماس"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"خواندن و نوشتن گزارش تماس تلفنی"</string>
- <string name="permgrouprequest_calllog" msgid="8487355309583773267">"به <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> اجازه میدهید به گزارش تماسهای تلفنی شما دسترسی داشته باشد؟"</string>
+ <string name="permgrouprequest_calllog" msgid="8487355309583773267">"به <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> اجازه داده شود به گزارش تماسهای تلفنی شما دسترسی داشته باشد؟"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"تلفن"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"برقراری و مدیریت تماسهای تلفنی"</string>
<string name="permgrouprequest_phone" msgid="9166979577750581037">"به <b><xliff:g id="APP_NAME">%1$s</xliff:g><b> اجازه داده شود تماسهای تلفنی برقرار کند و آنها را مدیریت کند؟"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"لطفاً چهرهتان را مجدداً ثبت کنید."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"دیگر چهره را تشخیص نمیدهد. دوباره امتحان کنید."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"بسیار شبیه قبلی است، لطفاً قیافه دیگری بگیرید."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"لطفاً مستقیم به صفحه نگاه کنید."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"لطفاً مستقیم به صفحه نگاه کنید."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"لطفاً سرتان را بهصورت عمود نگه دارید."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"هرگونه مانعی را بین سرتان و تلفن بردارید."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"لطفاً دوربین را تمیز کنید."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"سرتان را کمی پایین آورید."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"سرتان را کمی پایین آورید."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"سرتان را کمی پایین آورید."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"هرچیزی را که حائل چهرهتان است بردارید."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"حسگر واقع در لبه بالای صفحه را تمیز کنید."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"چهره تأیید نشد. سختافزار در دسترس نیست."</string>
@@ -2027,4 +2027,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> فایل</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"اشتراکگذاری مستقیم دردسترس نیست"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"فهرست برنامهها"</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 321228d..1ce4792 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -275,7 +275,7 @@
<string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
<string name="user_owner_label" msgid="8836124313744349203">"Vaihda henkilökohtaiseen profiiliin"</string>
<string name="managed_profile_label" msgid="8947929265267690522">"Vaihda työprofiiliin"</string>
- <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktit"</string>
+ <string name="permgrouplab_contacts" msgid="3657758145679177612">"Yhteystiedot"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"käyttää yhteystietoja"</string>
<string name="permgrouprequest_contacts" msgid="6032805601881764300">"Saako <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> yhteystietojesi käyttöoikeuden?"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Sijainti"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Rekisteröi kasvot uudelleen."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Ei enää tunnista kasvoja. Yritä uudelleen."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Liian samanlainen, vaihda asentoa."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Katso suoremmin näyttöön."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Katso suoremmin näyttöön."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Suorista pää pystysuunnassa."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Poista esteet pääsi ja puhelimen väliltä."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Puhdista kamera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Käännä päätä vähän vähemmän."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Käännä päätä vähän vähemmän."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Käännä päätä vähän vähemmän."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Poista esteet kasvojesi edestä."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Puhdista näytön yläreunassa oleva anturi."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Kasvoja ei voi vahvistaa. Laitteisto ei käytettäv."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> tiedosto</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Suora jakaminen ei käytettävissä"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Sovellusluettelo"</string>
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 6dd7401..b5b6130 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Veuillez inscrire votre visage à nouveau."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Ce visage ne sera plus reconnu. Réessayez."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Trop similaire. Changez de pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Veuillez regarder l\'écran plus directement."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Veuillez regarder l\'écran plus directement."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Veuillez redresse votre tête verticalement."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"L\'espace entre le tél. et votre tête doit être libre."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Veuillez nettoyer l\'objectif de l\'appareil photo."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Tournez un peu moins votre tête."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Tournez un peu moins votre tête."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Tournez un peu moins votre tête."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Retirez tout ce qui pourrait couvrir votre visage."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Nettoyez le capteur dans le haut de l\'écran."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Imposs. de vérif. visage. Matériel non accessible."</string>
@@ -2027,4 +2027,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichiers</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Le partage direct n\'est pas accessible"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Liste des applications"</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index c3285d6..965feb0 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -227,7 +227,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Urgences"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Rapport de bug"</string>
<string name="global_action_logout" msgid="935179188218826050">"Fermer la session"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"Capture d\'écran"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Capture"</string>
<string name="bugreport_title" msgid="5981047024855257269">"Rapport de bug"</string>
<string name="bugreport_message" msgid="398447048750350456">"Cela permet de recueillir des informations concernant l\'état actuel de votre appareil. Ces informations sont ensuite envoyées sous forme d\'e-mail. Merci de patienter pendant la préparation du rapport de bug. Cette opération peut prendre quelques instants."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Rapport interactif"</string>
@@ -301,7 +301,7 @@
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"Autoriser <xliff:g id="APP_NAME">%1$s</xliff:g> à accéder aux données relatives à votre activité physique ?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Appareil photo"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"prendre des photos et enregistrer des vidéos"</string>
- <string name="permgrouprequest_camera" msgid="1299833592069671756">"Autoriser l\'appli <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> à prendre des photos et enregistrer des vidéos ?"</string>
+ <string name="permgrouprequest_camera" msgid="1299833592069671756">"Autoriser <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> à prendre des photos et enregistrer des vidéos ?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Journaux d\'appels"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"Lire et écrire les journaux d\'appels du téléphone"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Autoriser l\'appli <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> à accéder aux journaux d\'appels de votre téléphone ?"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Veuillez enregistrer à nouveau votre visage."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Impossible de reconnaître le visage. Réessayez."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Ressemble à un visage existant, changez de pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Regardez plus directement l\'écran."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Regardez plus directement l\'écran."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Veuillez tenir votre tête droite."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Assurez-vous que rien ne cache votre visage."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Veuillez nettoyer l\'objectif de l\'appareil photo."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Tournez un peu moins la tête."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Tournez un peu moins la tête."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Tournez un peu moins la tête."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Retirez tout ce qui cache votre visage."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Nettoyez le capteur en haut de l\'écran."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Imposs. valider visage. Matériel non disponible."</string>
@@ -1364,7 +1364,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTAGER"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUSER"</string>
<string name="select_input_method" msgid="4653387336791222978">"Sélectionnez le mode de saisie"</string>
- <string name="show_ime" msgid="2506087537466597099">"Afficher l\'écran virtuel même lorsque le clavier physique est actif"</string>
+ <string name="show_ime" msgid="2506087537466597099">"Afficher le clavier virtuel même lorsque le clavier physique est actif"</string>
<string name="hardware" msgid="194658061510127999">"Afficher le clavier virtuel"</string>
<string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurer le clavier physique"</string>
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Appuyer pour sélectionner la langue et la disposition"</string>
@@ -2027,4 +2027,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichiers</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Le partage direct n\'est pas disponible"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Liste des applications"</string>
</resources>
diff --git a/core/res/res/values-gl-watch/strings.xml b/core/res/res/values-gl-watch/strings.xml
index 5e52823..701bda5 100644
--- a/core/res/res/values-gl-watch/strings.xml
+++ b/core/res/res/values-gl-watch/strings.xml
@@ -21,5 +21,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="android_upgrading_apk" msgid="1090732262010398759">"Aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
- <string name="permgrouplab_sensors" msgid="202675452368612754">"Sensores"</string>
+ <string name="permgrouplab_sensors" msgid="202675452368612754">"sensores"</string>
</resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index e71be82..dcaaebf 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -224,10 +224,10 @@
<string name="global_actions" product="default" msgid="2406416831541615258">"Opcións de teléfono"</string>
<string name="global_action_lock" msgid="2844945191792119712">"Bloqueo de pantalla"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"Apagar"</string>
- <string name="global_action_emergency" msgid="7112311161137421166">"Emerxencias"</string>
+ <string name="global_action_emergency" msgid="7112311161137421166">"Emerxencia"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Informe de erros"</string>
<string name="global_action_logout" msgid="935179188218826050">"Finalizar a sesión"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Capt. pantalla"</string>
<string name="bugreport_title" msgid="5981047024855257269">"Informe de erros"</string>
<string name="bugreport_message" msgid="398447048750350456">"Este informe recompilará información acerca do estado actual do teu dispositivo para enviala en forma de mensaxe de correo electrónico. O informe de erros tardará un pouco en completarse desde o seu inicio ata que estea preparado para enviarse, polo que che recomendamos que teñas paciencia."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Informe interactivo"</string>
@@ -266,7 +266,7 @@
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demostración comercial"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"conexión USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="6218742927792852607">"Estase executando a aplicación"</string>
- <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplicacións que consumen batería"</string>
+ <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplicacións que consomen batería"</string>
<string name="foreground_service_app_in_background" msgid="1060198778219731292">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo batería"</string>
<string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacións están consumindo batería"</string>
<string name="foreground_service_tap_for_details" msgid="372046743534354644">"Toca para obter información sobre o uso de datos e a batería"</string>
@@ -275,40 +275,40 @@
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="user_owner_label" msgid="8836124313744349203">"Cambiar ao perfil persoal"</string>
<string name="managed_profile_label" msgid="8947929265267690522">"Cambiar ao perfil de traballo"</string>
- <string name="permgrouplab_contacts" msgid="3657758145679177612">"contactos"</string>
+ <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceder aos teus contactos"</string>
<string name="permgrouprequest_contacts" msgid="6032805601881764300">"Queres permitir que a aplicación <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda aos teus contactos?"</string>
- <string name="permgrouplab_location" msgid="7275582855722310164">"localización"</string>
+ <string name="permgrouplab_location" msgid="7275582855722310164">"Localización"</string>
<string name="permgroupdesc_location" msgid="1346617465127855033">"acceder á localización deste dispositivo"</string>
- <string name="permgrouprequest_location" msgid="3788275734953323491">"Queres permitir que a aplicación <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda á localización deste dispositivo?"</string>
+ <string name="permgrouprequest_location" msgid="3788275734953323491">"Permitir que a aplicación <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda á localización deste dispositivo?"</string>
<string name="permgrouprequestdetail_location" msgid="1347189607421252902">"A aplicación só terá acceso á localización mentres a esteas utilizando"</string>
<string name="permgroupbackgroundrequest_location" msgid="5039063878675613235">"Queres permitir que <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda á localización deste dispositivo <b>sempre</b>?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="4597006851453417387">"Actualmente, a aplicación pode acceder á localización só mentres a utilices"</string>
- <string name="permgrouplab_calendar" msgid="5863508437783683902">"calendario"</string>
+ <string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendario"</string>
<string name="permgroupdesc_calendar" msgid="3889615280211184106">"acceder ao teu calendario"</string>
<string name="permgrouprequest_calendar" msgid="289900767793189421">"Queres permitir que a aplicación <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda ao teu calendario?"</string>
<string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
<string name="permgroupdesc_sms" msgid="4656988620100940350">"enviar e consultar mensaxes de SMS"</string>
<string name="permgrouprequest_sms" msgid="7168124215838204719">"Queres permitir que a aplicación <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> envíe e vexa mensaxes SMS?"</string>
- <string name="permgrouplab_storage" msgid="1971118770546336966">"almacenamento"</string>
+ <string name="permgrouplab_storage" msgid="1971118770546336966">"Almacenamento"</string>
<string name="permgroupdesc_storage" msgid="637758554581589203">"acceder a fotos, contido multimedia e ficheiros no teu dispositivo"</string>
<string name="permgrouprequest_storage" msgid="7885942926944299560">"Queres permitir que a aplicación <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda a fotos, contido multimedia e ficheiros no teu dispositivo?"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"Micrófono"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"gravar audio"</string>
<string name="permgrouprequest_microphone" msgid="9167492350681916038">"Queres permitir que a aplicación <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> grave audio?"</string>
- <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"actividade física"</string>
+ <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Actividade física"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"acceder á túa actividade física"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"Queres permitir que <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda á túa actividade física?"</string>
- <string name="permgrouplab_camera" msgid="4820372495894586615">"cámara"</string>
+ <string name="permgrouplab_camera" msgid="4820372495894586615">"Cámara"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"tirar fotos e gravar vídeos"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"Queres permitir que a aplicación <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> realice fotos e grave vídeos?"</string>
- <string name="permgrouplab_calllog" msgid="8798646184930388160">"rexistros de chamadas"</string>
+ <string name="permgrouplab_calllog" msgid="8798646184930388160">"Rexistros de chamadas"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"ler e editar o rexistro de chamadas do teléfono"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Queres permitir que <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda aos rexistros de chamadas do teléfono?"</string>
- <string name="permgrouplab_phone" msgid="5229115638567440675">"teléfono"</string>
+ <string name="permgrouplab_phone" msgid="5229115638567440675">"Teléfono"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"facer e xestionar chamadas telefónicas"</string>
<string name="permgrouprequest_phone" msgid="9166979577750581037">"Queres permitir que a aplicación <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> realice e xestione chamadas telefónicas?"</string>
- <string name="permgrouplab_sensors" msgid="4838614103153567532">"sensores corporais"</string>
+ <string name="permgrouplab_sensors" msgid="4838614103153567532">"Sensores corporais"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"acceder aos datos dos sensores sobre as túas constantes vitais"</string>
<string name="permgrouprequest_sensors" msgid="6349806962814556786">"Queres permitir que a aplicación <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda aos datos dos sensores sobre as túas constantes vitais?"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Recuperar contido da ventá"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Volve rexistrar a túa cara."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Xa non se pode recoñecer a cara. Téntao de novo."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"É moi similar. Cambia a pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Mira a pantalla de forma máis directa."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Mira a pantalla de forma máis directa."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Endereita a cabeza."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Quita o que haxa entre a túa cabeza e o teléfono."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Limpa a cámara."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Xira a cabeza un pouco menos."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Xira a cabeza un pouco menos."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Xira a cabeza un pouco menos."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Quita todo o que oculte a túa cara."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpa o sensor na parte superior da pantalla."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Sen verificar a cara. Hardware non dispoñible."</string>
@@ -808,7 +808,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Preme Menú para desbloquear ou realizar unha chamada de emerxencia."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Preme Menú para desbloquear."</string>
<string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Crea o padrón de desbloqueo"</string>
- <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Emerxencias"</string>
+ <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Emerxencia"</string>
<string name="lockscreen_return_to_call" msgid="5244259785500040021">"Volver á chamada"</string>
<string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Correcto!"</string>
<string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Téntao de novo"</string>
@@ -1596,7 +1596,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"Visualización sen fíos"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"Emitir"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"Conectar co dispositivo"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Emisión de pantalla no dispositivo"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Emitir pantalla en dispositivo"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"Buscando dispositivos…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Configuración"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Desconectar"</string>
@@ -1794,14 +1794,14 @@
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar PIN para soltar fixación"</string>
- <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar un padrón de desbloqueo antes de soltar a pantalla"</string>
- <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar un contrasinal antes de soltar a pantalla"</string>
+ <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar un padrón de desbloqueo antes de deixar de fixar a pantalla"</string>
+ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar un contrasinal para deixar de fixar a pantalla"</string>
<string name="package_installed_device_owner" msgid="6875717669960212648">"Instalado polo teu administrador"</string>
<string name="package_updated_device_owner" msgid="1847154566357862089">"Actualizado polo teu administrador"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"Eliminado polo teu administrador"</string>
<string name="confirm_battery_saver" msgid="639106420541753635">"Aceptar"</string>
- <string name="battery_saver_description_with_learn_more" msgid="2108984221113106294">"A función Aforro de batería desactiva ou restrinxe a actividade en segundo plano, algúns efectos visuais e outras funcións que consumen moita batería para que esta dure máis. "<annotation id="url">"Máis información"</annotation></string>
- <string name="battery_saver_description" msgid="6413346684861241431">"A función Aforro de batería desactiva ou restrinxe a actividade en segundo plano, algúns efectos visuais e outras funcións que consumen moita batería para que esta dure máis."</string>
+ <string name="battery_saver_description_with_learn_more" msgid="2108984221113106294">"A función Aforro de batería desactiva ou restrinxe a actividade en segundo plano, algúns efectos visuais e outras funcións que consomen moita batería para que esta dure máis. "<annotation id="url">"Máis información"</annotation></string>
+ <string name="battery_saver_description" msgid="6413346684861241431">"A función Aforro de batería desactiva ou restrinxe a actividade en segundo plano, algúns efectos visuais e outras funcións que consomen moita batería para que esta dure máis."</string>
<string name="data_saver_description" msgid="6015391409098303235">"Para contribuír a reducir o uso de datos, o Economizador de datos impide que algunhas aplicacións envíen ou reciban datos en segundo plano. Cando esteas utilizando unha aplicación, esta poderá acceder aos datos, pero é posible que o faga con menos frecuencia. Por exemplo, é posible que as imaxes non se mostren ata que as toques."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Queres activar o economizador de datos?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"Activar"</string>
@@ -2028,4 +2028,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ficheiro</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"A función de compartir directamente non está dispoñible"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lista de aplicacións"</string>
</resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index f708b7c9..5456a46 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"કૃપા કરીને તમારા ચહેરાની ફરી નોંધણી કરાવો."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"ચહેરો ઓળખી શકાતો નથી. ફરી પ્રયાસ કરો."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"ઘણી સમાનતા ધરાવે છે, કૃપા કરીને તમારો પોઝ બદલો."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"કૃપા કરીને સ્ક્રીન તરફ સીધું જુઓ."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"કૃપા કરીને સ્ક્રીન તરફ સીધું જુઓ."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"કૃપા કરીને તમારું માથું સીધું ઊભું રાખો."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"તમારા મસ્તક અને ફોન વચ્ચેની જગ્યા સાફ કરો."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"કૃપા કરીને કૅમેરા સાફ કરો."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"તમારું માથું થોડું ફેરવો."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"તમારું માથું થોડું ફેરવો."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"તમારું માથું થોડું ઓછું ફેરવો."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"તમારા ચહેરાને છુપાવતી કંઈપણ વસ્તુ દૂર કરો."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"સ્ક્રીનની ટોચની ધાર પરના સેન્સરને સાફ કરો."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ચહેરો ચકાસી શકાતો નથી. હાર્ડવેર ઉપલબ્ધ નથી."</string>
@@ -2028,4 +2028,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ફાઇલ</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"ડાયરેક્ટ શેર કરવાનું ઉપલબ્ધ નથી"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"ઍપની સૂચિ"</string>
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 1646812..65d87eb 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -42,8 +42,8 @@
<string name="serviceErased" msgid="1288584695297200972">"मिटाना सफल था."</string>
<string name="passwordIncorrect" msgid="7612208839450128715">"गलत पासवर्ड"</string>
<string name="mmiComplete" msgid="8232527495411698359">"MMI पूर्ण."</string>
- <string name="badPin" msgid="9015277645546710014">"आपके द्वारा लिखा गया पुराना पिन सही नहीं है."</string>
- <string name="badPuk" msgid="5487257647081132201">"आपके द्वारा लिखा गया PUK सही नहीं है."</string>
+ <string name="badPin" msgid="9015277645546710014">" लिखा गया पुराना पिन सही नहीं है."</string>
+ <string name="badPuk" msgid="5487257647081132201">" लिखा गया PUK सही नहीं है."</string>
<string name="mismatchPin" msgid="609379054496863419">"आपने जो पिन लिखे हैं उसका मिलान नहीं होता."</string>
<string name="invalidPin" msgid="3850018445187475377">"कोई ऐसा पिन लिखें, जिसमें 4 से 8 अंक हों."</string>
<string name="invalidPuk" msgid="8761456210898036513">"ऐसा PUK लिखें जो 8 अंकों या ज़्यादा का हो."</string>
@@ -180,11 +180,11 @@
<item quantity="other">प्रमाणपत्र अनुमतियों को इंस्टॉल किया गया</item>
</plurals>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"किसी अज्ञात तृतीय पक्ष के द्वारा"</string>
- <string name="ssl_ca_cert_noti_by_administrator" msgid="3541729986326153557">"आपकी कार्य प्रोफ़ाइल का व्यवस्थापक करता है"</string>
+ <string name="ssl_ca_cert_noti_by_administrator" msgid="3541729986326153557">"आपकी वर्क प्रोफ़ाइल का व्यवस्थापक करता है"</string>
<string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"<xliff:g id="MANAGING_DOMAIN">%s</xliff:g> के द्वारा"</string>
- <string name="work_profile_deleted" msgid="5005572078641980632">"कार्य प्रोफ़ाइल हटाई गई"</string>
- <string name="work_profile_deleted_details" msgid="6307630639269092360">"कार्य प्रोफ़ाइल व्यवस्थापक ऐप्लिकेशन या तो मौजूद नहीं है या वह खराब हो गया है. परिणामस्वरूप, आपकी कार्य प्रोफ़ाइल और उससे जुड़े डेटा को हटा दिया गया है. सहायता के लिए अपने व्यवस्थापक से संपर्क करें."</string>
- <string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"आपकी कार्य प्रोफ़ाइल अब इस डिवाइस पर उपलब्ध नहीं है"</string>
+ <string name="work_profile_deleted" msgid="5005572078641980632">"वर्क प्रोफ़ाइल हटाई गई"</string>
+ <string name="work_profile_deleted_details" msgid="6307630639269092360">"वर्क प्रोफ़ाइल व्यवस्थापक ऐप्लिकेशन या तो मौजूद नहीं है या वह खराब हो गया है. परिणामस्वरूप, आपकी वर्क प्रोफ़ाइल और उससे जुड़े डेटा को हटा दिया गया है. सहायता के लिए अपने व्यवस्थापक से संपर्क करें."</string>
+ <string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"आपकी वर्क प्रोफ़ाइल अब इस डिवाइस पर उपलब्ध नहीं है"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"कई बार गलत पासवर्ड डाला गया"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"डिवाइस प्रबंधित है"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"आपका संगठन इस डिवाइस का प्रबंधन करता है और वह नेटवर्क ट्रैफ़िक की निगरानी भी कर सकता है. विवरण के लिए टैप करें."</string>
@@ -274,7 +274,7 @@
<string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android सिस्टम"</string>
<string name="user_owner_label" msgid="8836124313744349203">"प्रोफ़ाइल बदलकर निजी प्रोफ़ाइल पर जाएं"</string>
- <string name="managed_profile_label" msgid="8947929265267690522">"प्रोफ़ाइल बदलकर कार्य प्रोफ़ाइल पर जाएं"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"प्रोफ़ाइल बदलकर वर्क प्रोफ़ाइल पर जाएं"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"संपर्क"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"अपने संपर्कों को ऐक्सेस करने की"</string>
<string name="permgrouprequest_contacts" msgid="6032805601881764300">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> को अपने संपर्क देखने की अनुमति देना चाहते हैं?"</string>
@@ -330,9 +330,9 @@
<string name="permlab_expandStatusBar" msgid="1148198785937489264">"स्टेटस बार खोलकर बड़ा करें/छोटा करें"</string>
<string name="permdesc_expandStatusBar" msgid="6917549437129401132">"ऐप को, स्टेटस बार खोलकर बड़ा करने या उसे छोटा करने की अनुमति देता है."</string>
<string name="permlab_install_shortcut" msgid="4279070216371564234">"शॉर्टकट इंस्टॉल करें"</string>
- <string name="permdesc_install_shortcut" msgid="8341295916286736996">"एप्लिकेशन को उपयोगकर्ता की रोक के बिना होमस्क्रीन शॉर्टकट जोड़ने की अनुमति देता है."</string>
+ <string name="permdesc_install_shortcut" msgid="8341295916286736996">"ऐप्लिकेशन को उपयोगकर्ता की रोक के बिना होमस्क्रीन शॉर्टकट जोड़ने की अनुमति देता है."</string>
<string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"शॉर्टकट अनइंस्टॉल करें"</string>
- <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"एप्लिकेशन को उपयोगकर्ता की रोक के बिना होमस्क्रीन शॉर्टकट निकालने की अनुमति देता है."</string>
+ <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ऐप्लिकेशन को उपयोगकर्ता की रोक के बिना होमस्क्रीन शॉर्टकट निकालने की अनुमति देता है."</string>
<string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"किया जाने वाला कॉल (आउटगोइंग) कहीं और भेजें"</string>
<string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"एेप कॉल को किसी और नंबर पर भेजने या कॉल को पूरी तरह रद्द करने के विकल्प के साथ, किए गए कॉल (आउटगोइंग) के नंबर को देख सकता है."</string>
<string name="permlab_answerPhoneCalls" msgid="4077162841226223337">"फ़ोन कॉल का जवाब दें"</string>
@@ -378,7 +378,7 @@
<string name="permlab_getPackageSize" msgid="7472921768357981986">"पता करें कि ऐप मेमोरी में कितनी जगह है"</string>
<string name="permdesc_getPackageSize" msgid="3921068154420738296">"ऐप को उसका कोड, डेटा, और कैश मेमोरी के आकारों को फिर से पाने देता है"</string>
<string name="permlab_writeSettings" msgid="2226195290955224730">"सिस्टम सेटिंग बदलें"</string>
- <string name="permdesc_writeSettings" msgid="7775723441558907181">"ऐप्स को सिस्टम सेटिंग डेटा संशोधित करने देता है. दुर्भावनापूर्ण ऐप्स आपके सिस्टम के कॉन्फ़िगरेशन को दूषित कर सकते हैं."</string>
+ <string name="permdesc_writeSettings" msgid="7775723441558907181">"ऐप्लिकेशन को सिस्टम सेटिंग डेटा में बदलाव करने देता है. नुकसान पहुंचाने वाले ऐप्लिकेशन आपके सिस्टम के कॉन्फ़िगरेशन को खराब सकते हैं."</string>
<string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"प्रारंभ होने पर चलाएं"</string>
<string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"ऐप्स को सिस्टम द्वारा बूटिंग पूर्ण करते ही अपने आप आरंभ करने देता है. इससे टैबलेट को आरंभ होने में ज़्यादा समय लग सकता है और ऐप्स को निरंतर चलाकर संपूर्ण टैबलेट को धीमा करने देता है."</string>
<string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"सिस्टम के चालू होते ही ऐप को अपने आप शुरू होने देती है. इससे टीवी को चालू होने में ज़्यादा समय लग सकता है और ऐप के लगातार चलते रहने से पूरा टैबलेट धीमा हो सकता है."</string>
@@ -392,9 +392,9 @@
<string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"ऐप को आपके टीवी पर मौजूद आपके संपर्कों का डेटा पढ़ने देती है, जिसमें ये भी शामिल है कि आपने कुछ ख़ास लोगों से कितनी बार कॉल, ईमेल, या कुछ और तरीकों से बातचीत की. यह अनुमति ऐप को आपका संपर्क डेटा सेव करने देती है और धोखा देने वाले ऐप संपर्क डेटा को आपकी जानकारी के बिना शेयर कर सकते हैं."</string>
<string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"ऐप को आपके फ़ोन पर मौजूद आपके संपर्कों का डेटा पढ़ने देती है, जिसमें ये भी शामिल है कि आपने कुछ ख़ास लोगों से कितनी बार कॉल, ईमेल, या कुछ और तरीकों से बातचीत की. यह अनुमति ऐप को आपका संपर्क डेटा सेव करने देती है और धोखा देने वाले ऐप, संपर्क डेटा को आपकी जानकारी के बिना शेयर कर सकते हैं."</string>
<string name="permlab_writeContacts" msgid="5107492086416793544">"अपने संपर्क बदलें"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ऐप्स को आपके टैबलेट में संग्रहित संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स को आपके संपर्क डेटा को हटाने देती है."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"ऐप को आपके टीवी पर संग्रहित आपके संपर्कों के बारे में संग्रहित डेटा में बदलाव करने देती है, जिसमें आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल भेजने या अन्य तरीकों से संचार किए जाने की आवृत्ति भी शामिल है. यह अनुमति ऐप्स को संपर्क डेटा हटाने देती है."</string>
- <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ऐप्स को आपके फ़ोन में संग्रहित संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स को आपके संपर्क डेटा को हटाने देती है."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ऐप्स को आपके टैबलेट में संग्रहित संपर्कों के डेटा को, साथ ही विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स को आपके संपर्क डेटा को हटाने देती है."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"ऐप को आपके टीवी पर संग्रहित आपके संपर्कों के बारे में संग्रहित डेटा में बदलाव करने देती है, जिसमें विशिष्ट व्यक्तियों को कॉल करने, ईमेल भेजने या अन्य तरीकों से संचार किए जाने की आवृत्ति भी शामिल है. यह अनुमति ऐप्स को संपर्क डेटा हटाने देती है."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ऐप्स को आपके फ़ोन में संग्रहित संपर्कों के डेटा को, साथ ही विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स को आपके संपर्क डेटा को हटाने देती है."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"कॉल लॉग पढ़ें"</string>
<string name="permdesc_readCallLog" msgid="3204122446463552146">"यह ऐप्लिकेशन आपका कॉल इतिहास पढ़ सकता है."</string>
<string name="permlab_writeCallLog" msgid="8552045664743499354">"कॉल लॉग लिखें"</string>
@@ -434,7 +434,7 @@
<string name="permlab_vibrate" msgid="7696427026057705834">"कंपन (वाइब्रेशन) को नियंत्रित करें"</string>
<string name="permdesc_vibrate" msgid="6284989245902300945">"ऐप्स को कंपनकर्ता नियंत्रित करने देता है."</string>
<string name="permlab_callPhone" msgid="3925836347681847954">"फ़ोन नंबर पर सीधे कॉल करें"</string>
- <string name="permdesc_callPhone" msgid="3740797576113760827">"ऐप्स को आपके हस्तक्षेप के बिना फ़ोन नंबर पर कॉल करने देता है. इसके परिणाम अप्रत्याशित शुल्क या कॉल हो सकते हैं. ध्यान दें कि यह ऐप्स को आपातकालीन नंबर पर कॉल नहीं करने देता. दुर्भावनापूर्ण ऐप्स आपकी पुष्टि के बिना कॉल करके आपका धन व्यय कर सकते हैं."</string>
+ <string name="permdesc_callPhone" msgid="3740797576113760827">"ऐप्लिकेशन को आपके हस्तक्षेप के बिना फ़ोन नंबर पर कॉल करने देता है. इसके परिणाम अनचाहे शुल्क या कॉल हो सकते हैं. ध्यान दें कि यह ऐप्लिकेशन को आपातकालीन नंबर पर कॉल नहीं करने देता. नुकसान पहुंचाने वाला ऐप्लिकेशन आपकी पुष्टि के बिना कॉल करके आपके पैसे खर्च करवा सकते हैं."</string>
<string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS कॉल सेवा ऐक्सेस करें"</string>
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"आपके हस्तक्षेप के बिना कॉल करने के लिए, ऐप को IMS सेवा का उपयोग करने देती है."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"फ़ोन की स्थिति और पहचान पढ़ें"</string>
@@ -466,9 +466,9 @@
<string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"ऐप को टीवी का समय क्षेत्र बदलने देती है."</string>
<string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"ऐप्स को टैबलेट का समय क्षेत्र बदलने देता है."</string>
<string name="permlab_getAccounts" msgid="1086795467760122114">"डिवाइस पर खाते ढूंढें"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"ऐप्स को टैबलेट द्वारा ज्ञात खातों की सूची प्राप्त करने देता है. इसमें वे खाते शामिल हो सकते हैं जिन्हें आपके द्वारा इंस्टॉल किए गए ऐप्स ने बनाया है."</string>
- <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"ऐप को टीवी द्वारा ज्ञात खातों की सूची प्राप्त करने देती है. इसमें आपके द्वारा इंस्टॉल किए गए ऐप्लिकेशन के द्वारा बनाए गए खाते शामिल हो सकते हैं."</string>
- <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"ऐप्स को फ़ोन द्वारा ज्ञात खातों की सूची प्राप्त करने देता है. इसमें वे खाते शामिल हो सकते हैं जिन्हें आपके द्वारा इंस्टॉल किए गए ऐप्स ने बनाया है."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"ऐप्स को टैबलेट द्वारा ज्ञात खातों की सूची प्राप्त करने देता है. इसमें वे खाते शामिल हो सकते हैं जिन्हें इंस्टॉल किए गए ऐप्स ने बनाया है."</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"ऐप को टीवी द्वारा ज्ञात खातों की सूची प्राप्त करने देती है. इसमें इंस्टॉल किए गए ऐप्लिकेशन के द्वारा बनाए गए खाते शामिल हो सकते हैं."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"ऐप्स को फ़ोन द्वारा ज्ञात खातों की सूची प्राप्त करने देता है. इसमें वे खाते शामिल हो सकते हैं जिन्हें इंस्टॉल किए गए ऐप्स ने बनाया है."</string>
<string name="permlab_accessNetworkState" msgid="4951027964348974773">"नेटवर्क कनेक्शन देखें"</string>
<string name="permdesc_accessNetworkState" msgid="8318964424675960975">"ऐप को नेटवर्क कनेक्शन के बारे में जानकारी देखने देता है, जैसे कौन से नेटवर्क मौजूद हैं और कनेक्ट हैं."</string>
<string name="permlab_createNetworkSockets" msgid="7934516631384168107">"नेटवर्क को पूरी तरह इस्तेमाल करें"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"कृपया फिर से अपने चेहरे की पहचान कराएं."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"अब चेहरे की पहचान नहीं कर पा रहा. फिर से कोशिश करें."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"चेहरा काफ़ी मिलता-जुलता है, कृपया अपना पोज़ बदलें."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"कृपया स्क्रीन की तरफ़ सीधा देखें."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"कृपया स्क्रीन की तरफ़ सीधा देखें."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"कृपया अपना सिर सीधा करें, दाएं-बाएं न झुकाएं"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"अपने सिर और फ़ोन के बीच की दूरी हटाएं."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"कृपया कैमरा साफ़ करें."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"अपना सिर थोड़ा कम घुमाएं."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"अपना सिर थोड़ा कम घुमाएं."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"अपना सिर थोड़ा कम घुमाएं"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"आपके चेहरे को छिपाने वाली सभी चीज़ों को हटाएं"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"स्क्रीन के ऊपरी किनारे पर मौजूद सेंसर को साफ करें."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"चेहरा नहीं पहचान पा रहे. हार्डवेयर उपलब्ध नहीं है."</string>
@@ -641,7 +641,7 @@
<string name="permlab_handoverStatus" msgid="7820353257219300883">"Android बीम ट्रांसफ़र की स्थिति पाएं"</string>
<string name="permdesc_handoverStatus" msgid="4788144087245714948">"इस एेप को मौजूदा Android बीम ट्रांसफ़र के बारे में जानकारी पाने की अनुमति दें."</string>
<string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"DRM प्रमाणपत्रों को निकाल सकता है"</string>
- <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"एप्लिकेशन को DRM प्रमाणपत्रों को निकालने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यकता नहीं होनी चाहिए."</string>
+ <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"ऐप्लिकेशन को DRM प्रमाणपत्रों को निकालने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यकता नहीं होनी चाहिए."</string>
<string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"किसी मोबाइल और इंटरनेट सेवा देने वाली कंपनी की संदेश सेवा से जुड़ें"</string>
<string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"उपयोगकर्ता को किसी मोबाइल और इंटरनेट सेवा देने वाली कंपनी की मैसेज सेवा के सबसे बढ़िया इंटरफ़ेस से जोड़ता है. सामान्य ऐप के लिए इसकी कभी ज़रूरत नहीं होती."</string>
<string name="permlab_bindCarrierServices" msgid="3233108656245526783">"किसी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से जुड़ें"</string>
@@ -1109,7 +1109,7 @@
<string name="define" msgid="7394820043869954211">"परिभाषित करें"</string>
<string name="define_desc" msgid="7910883642444919726">"चुना गया टेक्स्ट परिभाषित करें"</string>
<string name="low_internal_storage_view_title" msgid="5576272496365684834">"मेमोरी में जगह नहीं बची है"</string>
- <string name="low_internal_storage_view_text" msgid="6640505817617414371">"हो सकता है कुछ सिस्टम फ़ंक्शन कार्य न करें"</string>
+ <string name="low_internal_storage_view_text" msgid="6640505817617414371">"हो सकता है कुछ सिस्टम फ़ंक्शन काम नहीं करें"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"सिस्टम के लिए ज़रूरी मेमोरी नहीं है. पक्का करें कि आपके पास 250एमबी की खाली जगह है और फिर से शुरू करें."</string>
<string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> चल रहा है"</string>
<string name="app_running_notification_text" msgid="1197581823314971177">"ज़्यादा जानकारी के लिए या ऐप्लिकेशन को रोकने के लिए छूएं."</string>
@@ -1444,8 +1444,8 @@
<string name="deny" msgid="2081879885755434506">"अस्वीकारें"</string>
<string name="permission_request_notification_title" msgid="6486759795926237907">"अनुमति अनुरोधित"</string>
<string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"<xliff:g id="ACCOUNT">%s</xliff:g> खाते के लिए अनुमति\nका अनुरोध किया गया."</string>
- <string name="forward_intent_to_owner" msgid="1207197447013960896">"आप इस ऐप्स का उपयोग अपनी कार्य प्रोफ़ाइल से बाहर कर रहे हैं"</string>
- <string name="forward_intent_to_work" msgid="621480743856004612">"आप इस ऐप्स का उपयोग अपनी कार्य प्रोफ़ाइल में कर रहे हैं"</string>
+ <string name="forward_intent_to_owner" msgid="1207197447013960896">"आप इस ऐप्स का उपयोग अपनी वर्क प्रोफ़ाइल से बाहर कर रहे हैं"</string>
+ <string name="forward_intent_to_work" msgid="621480743856004612">"आप इस ऐप्स का उपयोग अपनी वर्क प्रोफ़ाइल में कर रहे हैं"</string>
<string name="input_method_binding_label" msgid="1283557179944992649">"इनपुट विधि"</string>
<string name="sync_binding_label" msgid="3687969138375092423">"समन्वयन"</string>
<string name="accessibility_binding_label" msgid="4148120742096474641">"सुलभता"</string>
@@ -1582,7 +1582,7 @@
<string name="activity_resolver_use_always" msgid="8017770747801494933">"हमेशा"</string>
<string name="activity_resolver_use_once" msgid="2404644797149173758">"केवल एक बार"</string>
<string name="activity_resolver_app_settings" msgid="8965806928986509855">"सेटिंग"</string>
- <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s कार्य प्रोफ़ाइल का समर्थन नहीं करता"</string>
+ <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s वर्क प्रोफ़ाइल का समर्थन नहीं करता"</string>
<string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"टैबलेट"</string>
<string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"टीवी"</string>
<string name="default_audio_route_name" product="default" msgid="4239291273420140123">"फ़ोन"</string>
@@ -1789,7 +1789,7 @@
<string name="select_day" msgid="7774759604701773332">"माह और दिन चुनें"</string>
<string name="select_year" msgid="7952052866994196170">"वर्ष चुनें"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> को हटा दिया गया"</string>
- <string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्यस्थल का <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge" msgid="2355652472854327647">"दफ़्तर का <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"दूसरा कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"तीसरा कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"अनपिन करने से पहले पिन के लिए पूछें"</string>
@@ -1859,7 +1859,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="6577956662913194947">"एसएस कोड चलाने के अनुरोध को वीडियो कॉल में बदला गया"</string>
<string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"एसएस कोड चलाने के अनुरोध को यूएसएसडी कोड चलाने के अनुरोध में बदला गया"</string>
<string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"एसएस कोड चलाने के नए अनुरोध में बदला गया"</string>
- <string name="notification_work_profile_content_description" msgid="4600554564103770764">"कार्य प्रोफ़ाइल"</string>
+ <string name="notification_work_profile_content_description" msgid="4600554564103770764">"वर्क प्रोफ़ाइल"</string>
<string name="notification_alerted_content_description" msgid="1296617716556420585">"अलर्ट किया गया"</string>
<string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"विस्तार करें"</string>
<string name="expand_button_content_description_expanded" msgid="8520652707158554895">"छोटा करें"</string>
@@ -1891,8 +1891,8 @@
<string name="app_suspended_title" msgid="2075071241147969611">"यह ऐप्लिकेशन उपलब्ध नहीं है"</string>
<string name="app_suspended_default_message" msgid="123166680425711887">"फ़िलहाल <xliff:g id="APP_NAME_0">%1$s</xliff:g> उपलब्ध नहीं है. इसे <xliff:g id="APP_NAME_1">%2$s</xliff:g> के ज़रिए प्रबंधित किया जाता है."</string>
<string name="app_suspended_more_details" msgid="1131804827776778187">"ज़्यादा जानें"</string>
- <string name="work_mode_off_title" msgid="1118691887588435530">"कार्य प्रोफ़ाइल चालू करें?"</string>
- <string name="work_mode_off_message" msgid="5130856710614337649">"आपके काम से जुड़े ऐप्लिकेशन, सूचनाएं, डेटा और कार्य प्रोफ़ाइल से जुड़ी दूसरी सुविधाएं चालू हो जाएंगी"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"वर्क प्रोफ़ाइल चालू करें?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"आपके काम से जुड़े ऐप्लिकेशन, सूचनाएं, डेटा और वर्क प्रोफ़ाइल से जुड़ी दूसरी सुविधाएं चालू हो जाएंगी"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"चालू करें"</string>
<string name="deprecated_target_sdk_message" msgid="1449696506742572767">"यह ऐप्लिकेशन Android के पुराने वर्शन के लिए बनाया गया था, इसलिए हो सकता है कि यह सही से काम न करे. देखें कि अपडेट मौजूद हैं या नहीं, या फिर डेवलपर से संपर्क करें."</string>
<string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"देखें कि अपडेट मौजूद है या नहीं"</string>
@@ -1901,7 +1901,7 @@
<string name="user_encrypted_title" msgid="9054897468831672082">"कुछ कार्य क्षमताएं सीमित हो सकती हैं"</string>
<string name="user_encrypted_message" msgid="4923292604515744267">"अनलॉक करने के लिए टैप करें"</string>
<string name="user_encrypted_detail" msgid="5708447464349420392">"उपयोगकर्ता डेटा लॉक किया गया"</string>
- <string name="profile_encrypted_detail" msgid="3700965619978314974">"कार्य प्रोफ़ाइल लॉक है"</string>
+ <string name="profile_encrypted_detail" msgid="3700965619978314974">"वर्क प्रोफ़ाइल लॉक है"</string>
<string name="profile_encrypted_message" msgid="6964994232310195874">"कार्य प्रोफाइल अनलॉक करने के लिए टैप करें"</string>
<string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> से कनेक्ट किया गया"</string>
<string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"फ़ाइलें देखने के लिए टैप करें"</string>
@@ -2027,4 +2027,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> फ़ाइलें</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"सीधे शेयर नहीं किया जा सकता"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"ऐप्लिकेशन की सूची"</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 79c0f82..01b2239 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -574,11 +574,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Ponovo registrirajte svoje lice."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Lice nije prepoznato. Pokušajte ponovo."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Previše slično, promijenite pozu."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Gledajte izravnije prema zaslonu."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Gledajte izravnije prema zaslonu."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Izravnajte glavu okomito."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Uklonite sve između svojeg lica i telefona."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Očistite fotoaparat."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Nagnite glavu malo manje."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Nagnite glavu malo manje."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Nagnite glavu malo manje."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Uklonite sve što vam zakriva lice."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Očistite senzor na gornjem rubu zaslona."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Lice nije potvrđeno. Hardver nije dostupan."</string>
@@ -1322,7 +1322,7 @@
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Upišite potreban PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
<string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"Tablet će se privremeno isključiti s Wi-Fija dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
- <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"Televizor će privremeno prekinuti vezu s Wi-Fi-jem dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"Televizor će privremeno prekinuti vezu s Wi-Fijem dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefon će se privremeno isključiti s Wi-Fija dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Umetni znak"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Slanje SMS poruka"</string>
@@ -2063,4 +2063,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> i još <xliff:g id="COUNT_3">%d</xliff:g> datoteka</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Izravno dijeljenje nije dostupno"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Popis aplikacija"</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d8c8071..c790311 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Rögzítsen újra képet az arcáról."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Már nem lehet felismerni az arcát. Próbálja újra."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Túlságosan hasonló, változtasson a pózon."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Szemből nézzen a képernyőre."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Szemből nézzen a képernyőre."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Fejét tartsa egyenesen, függőleges irányban."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Távolítson el mindent az arca és a telefon közül."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Tisztítsa meg a kamerát."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Kicsit kevésbé fordítsa el a fejét."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Kicsit kevésbé fordítsa el a fejét."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Kicsit kevésbé fordítsa el a fejét."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Távolítson el mindent, ami takarja az arcát."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Tisztítsa meg a képernyő tetején lévő érzékelőt."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Sikertelen arcellenőrzés. A hardver nem érhető el."</string>
@@ -1026,20 +1026,20 @@
<item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>é múlva</item>
</plurals>
<plurals name="duration_minutes_relative" formatted="false" msgid="3178131706192980192">
- <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> perccel ezelőtt</item>
- <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> perccel ezelőtt</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> perce</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> perce</item>
</plurals>
<plurals name="duration_hours_relative" formatted="false" msgid="676894109982008411">
- <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> órával ezelőtt</item>
- <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> órával ezelőtt</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> órája</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> órája</item>
</plurals>
<plurals name="duration_days_relative" formatted="false" msgid="2203515825765397130">
- <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> nappal ezelőtt</item>
- <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> nappal ezelőtt</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> napja</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> napja</item>
</plurals>
<plurals name="duration_years_relative" formatted="false" msgid="4820062134188885734">
- <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> évvel ezelőtt</item>
- <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> évvel ezelőtt</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> éve</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> éve</item>
</plurals>
<plurals name="duration_minutes_relative_future" formatted="false" msgid="4655043589817680966">
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> percen belül</item>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> fájl</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"A közvetlen megosztás nem áll rendelkezésre"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Alkalmazások listája"</string>
</resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 64013e7..4c27f21 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -218,7 +218,7 @@
<string name="reboot_safemode_title" msgid="7054509914500140361">"Վերաբեռնել անվտանգ ռեժիմի"</string>
<string name="reboot_safemode_confirm" msgid="55293944502784668">"Ցանկանու՞մ եք վերաբեռնել անվտանգ ռեժիմի: Սա կկասեցնի ձեր տեղադրած բոլոր կողմնակի ծրագրերը: Դրանք կվերականգնվեն, երբ դուք կրկին վերաբեռնեք:"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Վերջին"</string>
- <string name="no_recent_tasks" msgid="8794906658732193473">"Նոր հավելվածեր չկան:"</string>
+ <string name="no_recent_tasks" msgid="8794906658732193473">"Նոր հավելվածներ չկան:"</string>
<string name="global_actions" product="tablet" msgid="408477140088053665">"Պլանշետի ընտրանքները"</string>
<string name="global_actions" product="tv" msgid="7240386462508182976">"Հեռուստացույցի ընտրանքներ"</string>
<string name="global_actions" product="default" msgid="2406416831541615258">"Հեռախոսի ընտրանքներ"</string>
@@ -280,7 +280,7 @@
<string name="permgrouprequest_contacts" msgid="6032805601881764300">"Թույլատրե՞լ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> հավելվածին օգտագործել ձեր կոնտակտները"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Տեղորոշում"</string>
<string name="permgroupdesc_location" msgid="1346617465127855033">"տեղորոշել այս սարքը"</string>
- <string name="permgrouprequest_location" msgid="3788275734953323491">"Թույլատրե՞լ, որ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b>-ն օգտագործի այս սարքի տեղադրության տվյալները"</string>
+ <string name="permgrouprequest_location" msgid="3788275734953323491">"Թույլատրե՞լ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b>-ին օգտագործել այս սարքի տեղադրության տվյալները"</string>
<string name="permgrouprequestdetail_location" msgid="1347189607421252902">"Տեղադրության տվյալները հասանելի կլինեն հավելվածին, միայն երբ այն օգտագործելիս լինեք"</string>
<string name="permgroupbackgroundrequest_location" msgid="5039063878675613235">"<b>Միշտ</b> հասանելի դարձնե՞լ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> հավելվածին ձեր սարքի տեղադրությունը"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="4597006851453417387">"Տեղադրության տվյալները հասանելի կլինեն հավելվածին, միայն երբ այն օգտագործելիս լինեք"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Նորից փորձեք։"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Չհաջողվեց ճանաչել դեմքը։ Նորից փորձեք:"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Շատ նման է նախորդին։ Փոխեք ձեր դիրքը։"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Նայեք ուղիղ էկրանին։"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Նայեք ուղիղ էկրանին։"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Ուղղեք գլուխը հորիզոնական գծով։"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Գլխի և հեռախոսի միջև տարածությունը պետք է բաց լինի"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Մաքրեք տեսախցիկը։"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Գլուխն ուղիղ պահեք։"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Գլուխն ուղիղ պահեք։"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Գլուխն ուղիղ պահեք։"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Հեռացրեք այն ամենը, ինչը թաքցնում է ձեր երեսը:"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Մաքրեք էկրանի վերևի անկյունում գտնվող տվիչը:"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Չհաջողվեց հաստատել դեմքը։ Սարքն անհասանելի է:"</string>
@@ -2027,4 +2027,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ֆայլ</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Direct Share գործառույթը հասանելի չէ"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Հավելվածների ցանկ"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index c435324..8c9393d 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Daftarkan ulang wajah Anda."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Tidak lagi dapat mengenali wajah. Coba lagi."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Terlalu mirip, ubah pose Anda."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Lihat langsung ke layar."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Lihat langsung ke layar."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Luruskan kepala secara vertikal."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Pastikan wajah Anda tidak terhalang."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Harap bersihkan kamera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Putar sedikit kepala Anda."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Putar sedikit kepala Anda."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Putar sedikit kepala Anda."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Singkirkan apa saja yang menutupi wajah Anda."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Bersihkan sensor di tepi atas layar."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Tidak dapat memverifikasi wajah. Hardware tidak tersedia."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> file</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Berbagi langsung tidak tersedia"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Daftar aplikasi"</string>
</resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index a34d115..a2e058d 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Skráðu nafnið þitt aftur."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Andlit þekkist ekki lengur. Reyndu aftur."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Of svipað. Stilltu þér öðruvísi upp."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Horfðu beint á skjáinn."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Horfðu beint á skjáinn."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Vinsamlega réttu úr höfðinu."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Ekki hafa neitt milli höfuðsins og símans."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Hreinsaðu myndavélina."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Snúðu höfðinu aðeins minna."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Hallaðu höfðinu aðeins minna."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Snúðu höfðinu aðeins minna."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Fjarlægðu það sem kann að hylja andlitið."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Hreinsaðu skynjarann á efri brún skjásins."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Andlit ekki staðfest. Vélbúnaður er ekki tiltækur."</string>
@@ -2028,4 +2028,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> skrá</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Bein deiling er ekki tiltæk"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Forritalisti"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 3d4c2bd..623c044 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -278,7 +278,7 @@
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatti"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"accedere ai contatti"</string>
<string name="permgrouprequest_contacts" msgid="6032805601881764300">"Consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere ai tuoi contatti?"</string>
- <string name="permgrouplab_location" msgid="7275582855722310164">"Geolocalizzazione"</string>
+ <string name="permgrouplab_location" msgid="7275582855722310164">"Geolocalizz."</string>
<string name="permgroupdesc_location" msgid="1346617465127855033">"accedere alla posizione di questo dispositivo"</string>
<string name="permgrouprequest_location" msgid="3788275734953323491">"Consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere alla posizione di questo dispositivo?"</string>
<string name="permgrouprequestdetail_location" msgid="1347189607421252902">"L\'app avrà accesso alla posizione soltanto quando la usi"</string>
@@ -302,8 +302,8 @@
<string name="permgrouplab_camera" msgid="4820372495894586615">"Fotocamera"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"scattare foto e registrare video"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"Consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di scattare foto e registrare video?"</string>
- <string name="permgrouplab_calllog" msgid="8798646184930388160">"Registri chiamate"</string>
- <string name="permgroupdesc_calllog" msgid="3006237336748283775">"leggere e scrivere il registro chiamate del telefono"</string>
+ <string name="permgrouplab_calllog" msgid="8798646184930388160">"Log chiamate"</string>
+ <string name="permgroupdesc_calllog" msgid="3006237336748283775">"leggere e modificare il registro chiamate del telefono"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere ai registri chiamate del tuo telefono?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Telefono"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"eseguire e gestire le telefonate"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Ripeti l\'acquisizione del volto."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Non è più possibile riconoscere il volto. Riprova."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Troppo simile; cambia posa."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Guarda più direttamente verso lo schermo."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Guarda più direttamente verso lo schermo."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Raddrizza la testa in verticale."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Libera lo spazio tra la tua testa e il telefono."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Pulisci la fotocamera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Gira un po\' meno la testa."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Gira un po\' meno la testa."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Gira un po\' meno la testa."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Rimuovi tutto ciò che ti nasconde il viso."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Pulisci sensore sul bordo superiore dello schermo."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Imposs. verificare volto. Hardware non disponibile."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> file</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Condivisione diretta non attiva"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Elenco di app"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 5aaba62..fe481a4 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -577,11 +577,14 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"יש לרשום מחדש את הפנים."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"כבר לא ניתן לזהות פנים. יש לנסות שוב."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"דומה מדי, יש לשנות תנוחה."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"יש להביט ישירות אל המצלמה."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"יש להביט ישירות אל המצלמה."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"יש ליישר את הראש במאונך."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"הפנים שלך צריכים להיות גלויים לגמרי."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"צריך לנקות את המצלמה."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"עליך ליישר קצת את הראש."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"עליך ליישר קצת את הראש."</string>
+ <!-- no translation found for face_acquired_roll_too_extreme (6312973147689664409) -->
+ <skip />
+ <!-- no translation found for face_acquired_obscured (5357207702967893283) -->
+ <skip />
+ <!-- no translation found for face_acquired_sensor_dirty (2535761002815565222) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"לא ניתן לאמת את הפנים. החומרה לא זמינה."</string>
@@ -815,7 +818,7 @@
<string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"לחץ על \'תפריט\' כדי לבטל את הנעילה."</string>
<string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"שרטט קו לביטול נעילת המסך"</string>
<string name="lockscreen_emergency_call" msgid="5298642613417801888">"חירום"</string>
- <string name="lockscreen_return_to_call" msgid="5244259785500040021">"חזור לשיחה"</string>
+ <string name="lockscreen_return_to_call" msgid="5244259785500040021">"חזרה לשיחה"</string>
<string name="lockscreen_pattern_correct" msgid="9039008650362261237">"נכון!"</string>
<string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"נסה שוב"</string>
<string name="lockscreen_password_wrong" msgid="5737815393253165301">"נסה שוב"</string>
@@ -2099,4 +2102,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + קובץ אחד (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"שיתוף ישיר אינו זמין"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"רשימת האפליקציות"</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 3a6415b..532f1cb 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -227,7 +227,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"緊急通報"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"バグレポート"</string>
<string name="global_action_logout" msgid="935179188218826050">"セッションを終了"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"スクリーンショット"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"画面の保存"</string>
<string name="bugreport_title" msgid="5981047024855257269">"バグレポート"</string>
<string name="bugreport_message" msgid="398447048750350456">"現在のデバイスの状態に関する情報が収集され、その内容がメールで送信されます。バグレポートが開始してから送信可能な状態となるまでには多少の時間がかかりますのでご了承ください。"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"対話型レポート"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"顔を登録し直してください。"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"顔を認識できなくなりました。もう一度お試しください。"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"似すぎています。ポーズを変えてください。"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"もっとまっすぐ画面に顔を向けてください。"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"もっとまっすぐ画面に顔を向けてください。"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"頭を左右に傾けず、まっすぐにしてください。"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"顔とスマートフォンの間に何も置かないでください。"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"カメラの汚れを拭き取ってください。"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"顔の向きを少し戻してください。"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"顔の向きを少し戻してください。"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"顔の向きを少し戻してください。"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"顔を隠しているものをすべて外してください"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"画面の上端にあるセンサーの汚れを落としてください。"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"顔を確認できません。ハードウェアを利用できません。"</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g>、他 <xliff:g id="COUNT_1">%d</xliff:g> ファイル</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"ダイレクト シェアは利用できません"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"アプリのリスト"</string>
</resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index beb5e28..a610af3 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -228,7 +228,7 @@
<string name="global_action_bug_report" msgid="7934010578922304799">"ხარვეზის შესახებ ანგარიში"</string>
<string name="global_action_logout" msgid="935179188218826050">"სესიის დასრულება"</string>
<string name="global_action_screenshot" msgid="8329831278085426283">"ეკრანის ანაბეჭდი"</string>
- <string name="bugreport_title" msgid="5981047024855257269">"სისტ. ხარვეზ. ანგარ."</string>
+ <string name="bugreport_title" msgid="5981047024855257269">"ხარვეზის ანგარიში"</string>
<string name="bugreport_message" msgid="398447048750350456">"იგი შეაგროვებს ინფორმაციას თქვენი მოწყობილობის ამჟამინდელი მდგომარეობის შესახებ, რათა ის ელფოსტის შეტყობინების სახით გააგზავნოს. ხარვეზის ანგარიშის მომზადებასა და შეტყობინების გაგზავნას გარკვეული დრო სჭირდება. გთხოვთ, მოითმინოთ."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ინტერაქტიული ანგარიში"</string>
<string name="bugreport_option_interactive_summary" msgid="229299488536107968">"გამოიყენეთ ეს ვარიანტი შემთხვევათა უმეტესობაში. ის საშუალებას მოგცემთ, თვალი მიადევნოთ ანგარიშის პროგრესს, პრობლემის შესახებ მეტი დეტალი შეიყვანოთ და გადაიღოთ ეკრანის ანაბეჭდები. ამ ვარიანტის არჩევის შემთხვევაში, შეიძლება მოხდეს ზოგიერთი ნაკლებად გამოყენებადი სექციის გამოტოვება, რომელთა შესახებ მოხსენებასაც დიდი დრო სჭირდება."</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"გთხოვთ, ხელახლა დაარეგისტრიროთ თქვენი სახე."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"სახის ამოცნობა ვეღარ ხერხდება. ცადეთ ხელახლა."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"მეტისმეტად მსგავსია. გთხოვთ, შეცვალოთ პოზა."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"გთხოვთ, უფრო პირდაპირ შეხედოთ ეკრანს."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"გთხოვთ, უფრო პირდაპირ შეხედოთ ეკრანს."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"გთხოვთ, ვერტიკალურად გაასწოროთ თავი."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"გაათავისუფლეთ სივრცე თავსა და ტელეფონს შორის."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"გაწმინდეთ კამერა."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"თავი ცოტა ნაკლებად მიაბრუნეთ."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"თავი ცოტა ნაკლებად მიაბრუნეთ."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"თავი ცოტა ნაკლებად მიაბრუნეთ."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"მოაშორეთ ყველაფერი, რაც სახეს გიფარავთ."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"გაწმინდეთ სენსორი ეკრანის ზედა კიდეზე."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"სახე ვერ დასტურდება. აპარატი მიუწვდომელია."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ფაილი</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"პირდაპირი გაზიარება მიუწვდომელია"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"აპების სია"</string>
</resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 924c2a2..085b5d8 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -304,7 +304,7 @@
<string name="permgrouprequest_camera" msgid="1299833592069671756">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> қолданбасына суретке түсіруге және бейне жазуға рұқсат берілсін бе?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Қоңырау журналдары"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"телефонның қоңыраулар журналын оқу және жазу"</string>
- <string name="permgrouprequest_calllog" msgid="8487355309583773267">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> қолданбасына телефонның қоңыраулар журналына кіруге рұқсат етілсін бе?"</string>
+ <string name="permgrouprequest_calllog" msgid="8487355309583773267">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> қолданбасына телефонның қоңыраулар журналына кіруге рұқсат берілсін бе?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Телефон"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"қоңырау шалу және телефон қоңырауларын басқару"</string>
<string name="permgrouprequest_phone" msgid="9166979577750581037">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> қолданбасына қоңыраулар шалуға және басқаруға рұқсат берілсін бе?"</string>
@@ -555,7 +555,7 @@
<string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Қолданбаға бетті тану жабдығын қолдануға рұқсат етеді"</string>
<string name="face_recalibrate_notification_name" msgid="3976629945250435054">"Бетті тану"</string>
<string name="face_recalibrate_notification_title" msgid="4087620069451499365">"Бетті қайта тіркеу"</string>
- <string name="face_recalibrate_notification_content" msgid="5530308842361499835">"Құрылғы жүзіңізді жақсырақ тануы үшін, бетіңізді қайта тіркеңіз"</string>
+ <string name="face_recalibrate_notification_content" msgid="5530308842361499835">"Құрылғы жүзіңізді жақсырақ тануы үшін, бетіңізді қайта тіркеңіз."</string>
<string name="face_acquired_insufficient" msgid="2767330364802375742">"Бет деректері дұрыс алынбады. Әрекетті қайталаңыз."</string>
<string name="face_acquired_too_bright" msgid="5005650874582450967">"Тым ашық. Күңгірттеу жарық керек."</string>
<string name="face_acquired_too_dark" msgid="1966194696381394616">"Тым қараңғы. Молырақ жарық керек."</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Қайта тіркеліңіз."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Енді бет анықтау мүмкін емес. Әрекетті қайталаңыз."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Алдыңғысына тым ұқсас, басқаша қалыпта түсіңіз."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Камераға тура қараңыз."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Камераға тура қараңыз."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Басыңызды тік ұстаңыз."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Бетіңіз бен телефон арасында ештеңе тұрмауы керек."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Камераны тазалаңыз."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Басыңызды түзурек ұстаңыз."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Басыңызды түзурек ұстаңыз."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Басыңызды кішкене бұрыңыз."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Бетіңізді жауып тұрған нәрсені алып тастаңыз."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Экранның жоғарғы жиегіндегі датчикті тазалаңыз."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Бетті тану мүмкін емес. Жабдық қолжетімді емес."</string>
@@ -1596,7 +1596,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"Сымсыз дисплей"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"Трансляциялау"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"Құрылғыға жалғау"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Экранды құрылғымен байланыстыру"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Экран трансляциясы"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"Құрылғыларды іздеуде…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Параметрлер"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Ажырату"</string>
@@ -2028,4 +2028,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> файл</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Тікелей бөлісу мүмкін емес."</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Қолданбалар тізімі"</string>
</resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index f0333ab..3ef1bf0 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"សូមស្កេនបញ្ចូលមុខរបស់អ្នកម្ដងទៀត។"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"មិនអាចសម្គាល់មុខបានទៀតទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"ស្រដៀងគ្នាពេក សូមផ្លាស់ប្ដូរកាយវិការរបស់អ្នក។"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"សូមមើលឱ្យចំអេក្រង់ជាងមុន។"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"សូមមើលឱ្យចំអេក្រង់ជាងមុន។"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"សូមងើយក្បាលរបស់អ្នកឱ្យត្រង់។"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"កុំឱ្យមានអ្វីបាំងនៅចន្លោះក្បាល និងទូរសព្ទរបស់អ្នក។"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"សូមសម្អាតកាមេរ៉ា។"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"ងាកក្បាលរបស់អ្នកបន្តិចទៀត។"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ងាកក្បាលរបស់អ្នកបន្តិចទៀត។"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ងាកក្បាលរបស់អ្នកបន្តិចទៀត។"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"យកអ្វីដែលបាំងមុខរបស់អ្នកចេញ។"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"សម្អាតឧបករណ៍ចាប់សញ្ញានៅគែមខាងលើនៃអេក្រង់។"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"មិនអាចផ្ទៀងផ្ទាត់មុខបានទេ។ មិនមានហាតវែរទេ។"</string>
@@ -1597,7 +1597,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"បង្ហាញបណ្ដាញឥតខ្សែ"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"បញ្ជូន"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"ភ្ជាប់ឧបករណ៍"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ខាសអេក្រង់ទៅឧបករណ៍"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ភ្ជាប់អេក្រង់ទៅឧបករណ៍"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"កំពុងស្វែងរកឧបករណ៍..."</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"ការកំណត់"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"ផ្ដាច់"</string>
@@ -2029,4 +2029,5 @@
<item quantity="one">ឯកសារ <xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g></item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"មិនមានការចែករំលែកដោយផ្ទាល់ទេ"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"បញ្ជីកម្មវិធី"</string>
</resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index aac9b05..dab10df 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"ನಿಮ್ಮ ಮುಖವನ್ನು ಮರುನೋಂದಣಿ ಮಾಡಿ."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"ಮುಖ ಗುರುತಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"ತುಂಬಾ ಸಮಾನ, ನಿಮ್ಮ ಪೋಸ್ ಬದಲಾಯಿಸಿ."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"ಸ್ಕ್ರೀನ್ ಕಡೆ ಹೆಚ್ಚು ನೇರವಾಗಿ ನೋಡಿ."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"ಸ್ಕ್ರೀನ್ ಕಡೆ ಹೆಚ್ಚು ನೇರವಾಗಿ ನೋಡಿ."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"ನಿಮ್ಮ ತಲೆಯನ್ನು ವರ್ಟಿಕಲ್ ಆಗಿ ನೇರವಾಗಿಸಿ."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"ನಿಮ್ಮ ತಲೆ ಮತ್ತು ಫೋನ್ ನಡುವಿನ ಅಡಚಣೆಯನ್ನು ತೆರವುಗೊಳಿಸಿ"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"ಕ್ಯಾಮರಾವನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸಿ."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"ನಿಮ್ಮ ತಲೆಯನ್ನು ಹೆಚ್ಚು ತಿರುಗಿಸಬೇಡಿ."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ನಿಮ್ಮ ತಲೆಯನ್ನು ಹೆಚ್ಚು ತಿರುಗಿಸಬೇಡಿ."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ನಿಮ್ಮ ತಲೆಯನ್ನು ಸ್ವಲ್ಪ ಕಡಿಮೆ ತಿರುಗಿಸಿ."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"ನಿಮ್ಮ ಮುಖವನ್ನು ಮರೆಮಾಡುವ ಯಾವುದನ್ನಾದರೂ ತೆಗೆದುಹಾಕಿ."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"ಸ್ಕ್ರೀನ್ ಮೇಲ್ಬಾಗದ ಅಂಚಿನಲ್ಲಿನ ಸೆನ್ಸರ್ ಸ್ವಚ್ಚಗೊಳಿಸಿ."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ಮುಖ ದೃಢೀಕರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಹಾರ್ಡ್ವೇರ್ ಲಭ್ಯವಿಲ್ಲ."</string>
@@ -1366,7 +1366,7 @@
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ನಿರಾಕರಿಸಿ"</string>
<string name="select_input_method" msgid="4653387336791222978">"ಇನ್ಪುಟ್ ವಿಧಾನವನ್ನು ಆರಿಸಿ"</string>
<string name="show_ime" msgid="2506087537466597099">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್ ಸಕ್ರಿಯವಾಗಿರುವಾಗ ಅದನ್ನು ಪರದೆಯ ಮೇಲಿರಿಸಿ"</string>
- <string name="hardware" msgid="194658061510127999">"ವರ್ಚ್ಯುಯಲ್ ಕೀಬೋರ್ಡ್ ತೋರಿಸು"</string>
+ <string name="hardware" msgid="194658061510127999">"ವರ್ಚುವಲ್ ಕೀಬೋರ್ಡ್ ತೋರಿಸಿ"</string>
<string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್ ಕಾನ್ಫಿಗರ್ ಮಾಡಿ"</string>
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ಭಾಷೆ ಮತ್ತು ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1596,7 +1596,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"ವಯರ್ಲೆಸ್ ಪ್ರದರ್ಶನ"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"ಪಾತ್ರ"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"ಸಾಧನಕ್ಕೆ ಸಂಪರ್ಕಿಸಿ"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ಸಾಧನಕ್ಕೆ ಬಿತ್ತರಿಸುವ ಪರದೆ"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ಪರದೆಯನ್ನು ಸಾಧನದಲ್ಲಿ ಬಿತ್ತರಿಸಿ"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"ಸಾಧನಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸು"</string>
@@ -2028,4 +2028,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ಫೈಲ್ಗಳು</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"ನೇರ ಹಂಚಿಕೆ ಲಭ್ಯವಿಲ್ಲ"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"ಆ್ಯಪ್ಗಳ ಪಟ್ಟಿ"</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 22e9d03..9a76aa2 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -304,7 +304,7 @@
<string name="permgrouprequest_camera" msgid="1299833592069671756">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>에서 사진을 촬영하고 동영상을 녹화하도록 허용하시겠습니까?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"통화 기록"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"통화 기록 읽고 쓰기"</string>
- <string name="permgrouprequest_calllog" msgid="8487355309583773267">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>이(가) 통화 기록에 액세스하도록 허용하시겠습니까?"</string>
+ <string name="permgrouprequest_calllog" msgid="8487355309583773267">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>에서 통화 기록에 액세스하도록 허용하시겠습니까?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"전화"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"전화 걸기 및 관리"</string>
<string name="permgrouprequest_phone" msgid="9166979577750581037">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>에서 전화를 걸고 관리하도록 허용하시겠습니까?"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"얼굴을 다시 등록해 주세요."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"더 이상 얼굴을 인식할 수 없습니다. 다시 시도하세요."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"너무 비슷합니다. 다른 포즈를 취해 보세요."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"화면을 더 똑바로 바라보세요."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"화면을 더 똑바로 바라보세요."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"고개를 똑바로 세워 주세요."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"얼굴과 휴대전화 사이의 공간을 비워두세요."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"카메라의 이물질을 제거하세요."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"고개를 조금 덜 돌려 보세요."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"고개를 조금 덜 돌려 보세요."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"고개를 조금 덜 돌려 보세요."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"얼굴이 가려지지 않도록 해 주세요."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"화면 상단 가장자리의 센서를 깨끗하게 닦아 주세요."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"얼굴을 확인할 수 없습니다. 하드웨어를 사용할 수 없습니다."</string>
@@ -982,8 +982,8 @@
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>년"</string>
<string name="day" msgid="8144195776058119424">"일"</string>
<string name="days" msgid="4774547661021344602">"일"</string>
- <string name="hour" msgid="2126771916426189481">"시간"</string>
- <string name="hours" msgid="894424005266852993">"시간"</string>
+ <string name="hour" msgid="2126771916426189481">"시"</string>
+ <string name="hours" msgid="894424005266852993">"시"</string>
<string name="minute" msgid="9148878657703769868">"분"</string>
<string name="minutes" msgid="5646001005827034509">"분"</string>
<string name="second" msgid="3184235808021478">"초"</string>
@@ -1846,7 +1846,7 @@
<string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"다운타임"</string>
<string name="zen_mode_default_weeknights_name" msgid="3081318299464998143">"평일 밤"</string>
<string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"주말"</string>
- <string name="zen_mode_default_events_name" msgid="8158334939013085363">"캘린더 일정"</string>
+ <string name="zen_mode_default_events_name" msgid="8158334939013085363">"캘린더 일정 중"</string>
<string name="zen_mode_default_every_night_name" msgid="3012363838882944175">"수면 중"</string>
<string name="muted_by" msgid="5942954724562097128">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>(이)가 일부 소리를 음소거함"</string>
<string name="system_error_wipe_data" msgid="6608165524785354962">"사용 중인 기기 내부에 문제가 발생했습니다. 초기화할 때까지 불안정할 수 있습니다."</string>
@@ -1922,7 +1922,7 @@
<string name="app_category_productivity" msgid="3742083261781538852">"생산성"</string>
<string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"기기 저장용량"</string>
<string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"USB 디버깅"</string>
- <string name="time_picker_hour_label" msgid="2979075098868106450">"시간"</string>
+ <string name="time_picker_hour_label" msgid="2979075098868106450">"시"</string>
<string name="time_picker_minute_label" msgid="5168864173796598399">"분"</string>
<string name="time_picker_header_text" msgid="143536825321922567">"시간 설정"</string>
<string name="time_picker_input_error" msgid="7574999942502513765">"올바른 시간을 입력하세요."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> 및 파일 <xliff:g id="COUNT_1">%d</xliff:g>개</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"직접 공유가 지원되지 않음"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"앱 목록"</string>
</resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 9b51336..663e48b 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -87,7 +87,7 @@
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"Тандалган тармакты өзгөртүп көрүңүз. Өзгөртүү үчүн таптаңыз."</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Шашылыш чалуу жеткиликсиз"</string>
<string name="EmergencyCallWarningSummary" msgid="1899692069750260619">"Wi-Fi аркылуу шашылыш чалуулар иштетилген жок"</string>
- <string name="notification_channel_network_alert" msgid="4427736684338074967">"Эскертүүлөр"</string>
+ <string name="notification_channel_network_alert" msgid="4427736684338074967">"Шашылыш билдирүүлөр"</string>
<string name="notification_channel_call_forward" msgid="2419697808481833249">"Чалууну башка номерге багыттоо"</string>
<string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Шашылыш кайра чалуу режими"</string>
<string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Мобилдик Интернеттин абалы"</string>
@@ -262,7 +262,7 @@
<string name="notification_channel_network_available" msgid="4531717914138179517">"Жеткиликтүү тармактар"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN абалы"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Түзмөктү администрациялоо"</string>
- <string name="notification_channel_alerts" msgid="4496839309318519037">"Эскертүүлөр"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"Шашылыш билдирүүлөр"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Чекене соода дүкөнү үчүн демо режим"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB аркылуу туташуу"</string>
<string name="notification_channel_heavy_weight_app" msgid="6218742927792852607">"Колдонмо иштеп жатат"</string>
@@ -295,19 +295,19 @@
<string name="permgrouprequest_storage" msgid="7885942926944299560">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна түзмөгүңүздөгү сүрөттөрдү жана башка мультимедиа файлдарын пайдаланууга уруксат бересизби?"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"аудио жаздыруу"</string>
- <string name="permgrouprequest_microphone" msgid="9167492350681916038">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна аудио файлдарды жаздырууга уруксат берилсинби?"</string>
+ <string name="permgrouprequest_microphone" msgid="9167492350681916038">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна аудио файлдарды жазганга уруксат бересизби?"</string>
<string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Кыймыл-аракет"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"кыймыл-аракетиңизге мүмкүнчүлүк алат"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна кыймыл-аракетиңизге мүмкүнчүлүк бересизби?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"сүрөт жана видео тартууга"</string>
- <string name="permgrouprequest_camera" msgid="1299833592069671756">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна сүрөттөрдү тартып, видеолорду жаздырууга уруксат берилсинби?"</string>
+ <string name="permgrouprequest_camera" msgid="1299833592069671756">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна сүрөттөр менен видеолорду тартканга уруксат бересизби?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Чалуулар тизмелери"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"телефондогу чалуулар тизмесин окуу жана жазуу"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна телефондогу чалуулар тизмесин пайдаланууга уруксат берилсинби?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Телефон"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"телефон чалуу жана аларды башкаруу"</string>
- <string name="permgrouprequest_phone" msgid="9166979577750581037">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна телефон чалууга жана чалууларды башкарууга уруксат берилсинби?"</string>
+ <string name="permgrouprequest_phone" msgid="9166979577750581037">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна телефон чалууга жана чалууларды башкарууга уруксат бересизби?"</string>
<string name="permgrouplab_sensors" msgid="4838614103153567532">"Дене сенсорлору"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"организмдин абалына көз салган сенсордун дайындарына мүмкүнчүлүк алуу"</string>
<string name="permgrouprequest_sensors" msgid="6349806962814556786">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна организмдин абалына көз салган сенсордун көрсөткүчтөрүн көрүүгө уруксат бересизби?"</string>
@@ -548,7 +548,7 @@
<string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g>-манжа"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Манжа изинин сөлөкөтү"</string>
+ <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Манжа изинин сүрөтчөсү"</string>
<string name="permlab_manageFace" msgid="2137540986007309781">"жүздүн аныктыгын текшерүүчү аппараттык камсыздоону башкаруу"</string>
<string name="permdesc_manageFace" msgid="8919637120670185330">"Колдонмого пайдалануу үчүн жүздүн үлгүлөрүн кошуу жана жок кылуу мүмкүндүгүн берет."</string>
<string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"жүздүн аныктыгын текшерүүчү аппараттык камсыздоону колдонуу"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Жүзүңүздү кайра таанытыңыз."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Жүз таанылган жок. Кайра аракет кылыңыз."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Мурункуга окшош болуп калды, башкача туруңуз."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Дисплейге түз караңыз."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Дисплейге түз караңыз."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Башыңызды түз кармаңыз."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Башыңыз менен телефондун ортосу бош болушу керек."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Камераны тазалаңыз."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Башыңызды бир аз гана эңкейтиңиз."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Башыңызды бир аз гана эңкейтиңиз."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Башыңызды бир аз гана эңкейтиңиз."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Жүзүңүздү жашырып турган нерселерди алып салыңыз."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Экрандын жогору жагындагы сенсорду тазалаңыз."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Жүз ырасталбай жатат. Аппараттык камсыздоо жеткиликсиз."</string>
@@ -1597,7 +1597,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"Зымсыз дисплей"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"Тышкы экранга чыгаруу"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"Түзмөккө туташуу"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Сырткы экранга чыгаруу"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Тышкы экранга чыгаруу"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"Түзмөктөр изделүүдө..."</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Жөндөөлөр"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Ажыратуу"</string>
@@ -1928,7 +1928,7 @@
<string name="time_picker_minute_label" msgid="5168864173796598399">"мүнөт"</string>
<string name="time_picker_header_text" msgid="143536825321922567">"Убакытты коюу"</string>
<string name="time_picker_input_error" msgid="7574999942502513765">"Убакытты туура көрсөтүңүз"</string>
- <string name="time_picker_prompt_label" msgid="7588093983899966783">"Убакытты жазыңыз"</string>
+ <string name="time_picker_prompt_label" msgid="7588093983899966783">"Убакытты киргизиңиз"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Убакытты текст киргизүү режиминде киргизиңиз."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Убакытты дубал саатынын режиминде киргизиңиз."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Автотолтуруу опциялары"</string>
@@ -2029,4 +2029,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> файл</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Түздөн-түз бөлүшүүгө болбойт"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Колдонмолордун тизмеси"</string>
</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 5b7c722..e3cd3f9 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"ກະລຸນາລົງທະບຽນອຸປະກອນຂອງທ່ານອີກເທື່ອໜຶ່ງ."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"ບໍ່ສາມາດຈຳແນກໃບໜ້າໄດ້ອີກຕໍ່ໄປ. ກະລຸນາລອງໃໝ່."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"ຄ້າຍກັນເກີນໄປ, ກະລຸນາປ່ຽນທ່າຂອງທ່ານ."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"ກະລຸນາເບິ່ງຊື່ໆໄປທາງໜ້າຈໍຫຼາຍຂຶ້ນ."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"ກະລຸນາເບິ່ງຊື່ໆໄປທາງໜ້າຈໍຫຼາຍຂຶ້ນ."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"ກະລຸນາຍັບຫົວຂອງທ່ານໃຫ້ຊື່ຕາມລວງຕັ້ງ."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"ເຄລຍພື້ນທີ່ລະຫວ່າງຫົວ ແລະ ໂທລະສັບຂອງທ່ານ."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"ກະລຸນາທຳຄວາມສະອາດກ້ອງ."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"ອຽງຫົວຂອງທ່ານໜ້ອຍໜຶ່ງ."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ອຽງຫົວຂອງທ່ານໜ້ອຍໜຶ່ງ."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ອຽງຫົວຂອງທ່ານໜ້ອຍໜຶ່ງ."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"ນຳສິ່ງທີ່ກີດຂວາງໃບໜ້າທ່ານອອກ."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"ທຳຄວາມສະອາດເຊັນເຊີຢູ່ເທິງສຸດຂອງຂອບຈໍ."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ບໍ່ສາມາດຢັ້ງຢືນໃບໜ້າໄດ້. ບໍ່ມີຮາດແວໃຫ້ໃຊ້."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ໄຟລ໌</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"ບໍ່ສາມາດແບ່ງປັນໂດຍກົງໄດ້"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"ລາຍຊື່ແອັບ"</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 6095e56..f03a2c8 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -577,11 +577,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Užregistruokite veidą iš naujo."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Nebegalima atpažinti veido. Bandykite dar kartą."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Per daug panašu, pakeiskite veido išraišką."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Žiūrėkite tiesiai į ekraną."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Žiūrėkite tiesiai į ekraną."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Laikykite galvą vertikaliai."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Nieko negali būti tarp galvos ir telefono."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Nuvalykite fotoaparatą."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Nesukite tiek galvos."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Nesukite tiek galvos."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Nesukite tiek galvos."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Patraukite viską, kas užstoja jūsų veidą."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Nuvalykite jutiklį, esantį ekrano viršuje."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nepavyko patv. veido. Aparatinė įranga negalima."</string>
@@ -2099,4 +2099,5 @@
<item quantity="other">„<xliff:g id="FILE_NAME_2">%s</xliff:g>“ ir <xliff:g id="COUNT_3">%d</xliff:g> failų</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Tiesioginio bendrinimo funkcija nepasiekiama"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Programų sąrašas"</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index b5722a5..8e7ec08 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -574,11 +574,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Lūdzu, atkārtoti reģistrējiet savu seju."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Seju vairs nevar atpazīt. Mēģiniet vēlreiz."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Pārāk līdzīgi. Lūdzu, mainiet pozu."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Lūdzu, tiešāk skatieties uz ekrānu."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Lūdzu, tiešāk skatieties uz ekrānu."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Lūdzu, vertikāli iztaisnojiet galvu."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Atbrīvojiet vietu starp savu galvu un tālruni."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Lūdzu, notīriet kameru."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Pagrieziet galvu nedaudz mazāk."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Pagrieziet galvu nedaudz mazāk."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Pagrieziet galvu nedaudz mazāk."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Noņemiet visu, kas aizsedz jūsu seju."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Notīriet sensoru ekrāna augšējā malā."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nevar verificēt seju. Aparatūra nav pieejama."</string>
@@ -2063,4 +2063,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> un <xliff:g id="COUNT_3">%d</xliff:g> faili</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Tiešā kopīgošana nav pieejama"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lietotņu saraksts"</string>
</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 91620c4..dd8c6c2 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Повторно регистрирајте го лицето."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Ликот не се препознава. Обидете се повторно."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Премногу слично, сменете ја позата."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Гледајте право во екранот."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Гледајте право во екранот."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Исправете ја главата вертикално."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Исчистете го просторот меѓу главата и телефонот"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Исчистете ја камерата."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Не вртете ја главата толку многу."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Не вртете ја главата толку многу."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Не вртете ја главата толку многу."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Отстранете ги работите што ви го покриваат лицето."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Исчистете го сензорот на горниот врв од екранот."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Ликот не може да се потврди. Хардвер - недостапен."</string>
@@ -1599,7 +1599,7 @@
<string name="media_route_button_content_description" msgid="591703006349356016">"Емитувај"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"Поврзи се со уред"</string>
<string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Префрли екран на уред"</string>
- <string name="media_route_chooser_searching" msgid="4776236202610828706">"Пребарување за уреди..."</string>
+ <string name="media_route_chooser_searching" msgid="4776236202610828706">"Се бараат уреди..."</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Поставки"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Исклучи"</string>
<string name="media_route_status_scanning" msgid="7279908761758293783">"Скенирање..."</string>
@@ -1804,7 +1804,7 @@
<string name="confirm_battery_saver" msgid="639106420541753635">"Во ред"</string>
<string name="battery_saver_description_with_learn_more" msgid="2108984221113106294">"Штедачот на батерија ги исклучува или ограничува активноста во заднина, некои визуелни ефекти и други функции со голема потрошувачка на енергија за да се продолжи траењето на батеријата. "<annotation id="url">"Дознајте повеќе"</annotation></string>
<string name="battery_saver_description" msgid="6413346684861241431">"Штедачот на батерија ги исклучува или ограничува активноста во заднина, некои визуелни ефекти и други функции со голема потрошувачка на енергија за да се продолжи траењето на батеријата."</string>
- <string name="data_saver_description" msgid="6015391409098303235">"За да се намали користењето интернет, Штедачот на интернет спречува дел од апликациите да испраќаат или да примаат податоци во заднина. Апликацијата што ја користите во моментов можеби ќе пристапува до интернет, но тоа ќе го прави поретко. Ова значи, на пример, дека сликите нема да се прикажат додека не ги допрете."</string>
+ <string name="data_saver_description" msgid="6015391409098303235">"За да се намали користењето интернет, „Штедачот на интернет“ спречува дел од апликациите да испраќаат или да примаат податоци во заднина. Апликацијата што ја користите во моментов можеби ќе пристапува до интернет, но тоа ќе го прави поретко. Ова значи, на пример, дека сликите нема да се прикажат додека не ги допрете."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Вклучете Штедач на интернет?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"Вклучи"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
@@ -2030,4 +2030,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> датотеки</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Директно споделување не е достапно"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Список со апликации"</string>
</resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 44fe171..10e16ca 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -526,7 +526,7 @@
<string name="biometric_error_canceled" msgid="349665227864885880">"പരിശോധിച്ചുറപ്പിക്കൽ റദ്ദാക്കി"</string>
<string name="biometric_error_device_not_secured" msgid="6583143098363528349">"പിന്നോ പാറ്റേണോ പാസ്വേഡോ സജ്ജീകരിച്ചിട്ടില്ല"</string>
<string name="fingerprint_acquired_partial" msgid="735082772341716043">"വിരലടയാളം ഭാഗികമായി തിരിച്ചറിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
- <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"വിരലടയാളം പ്രോസസ്സ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+ <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"വിരലടയാളം പ്രോസസ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"വിരലടയാള സെൻസറിൽ ചെളിയുണ്ട്. അത് വൃത്തിയാക്കി വീണ്ടും ശ്രമിക്കുക."</string>
<string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"വിരൽ വളരെ വേഗത്തിൽ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string>
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"വിരൽ വളരെ പതുക്കെ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string>
@@ -571,11 +571,14 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"നിങ്ങളുടെ മുഖം വീണ്ടും എൻറോൾ ചെയ്യുക."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"ഇനി മുഖം തിരിച്ചറിയാനാവില്ല. വീണ്ടും ശ്രമിക്കൂ."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"വളരെയധികം സമാനത, നിങ്ങളുടെ പോസ് മാറ്റുക."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"അൽപ്പം കൂടി സ്ക്രീനിന് നേരെ നോക്കുക."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"അൽപ്പം കൂടി സ്ക്രീനിന് നേരെ നോക്കുക."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"നിങ്ങളുടെ തല ലംബമായി നേരെയാക്കുക"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"തലയ്ക്കും ഫോണിനുമിടയിലുള്ള തടസ്സം നീക്കുക."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"ക്യാമറ വൃത്തിയാക്കുക."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"നിങ്ങളുടെ തല ഇത്ര തിരിക്കേണ്ട."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"നിങ്ങളുടെ തല ഇത്ര തിരിക്കേണ്ട."</string>
+ <!-- no translation found for face_acquired_roll_too_extreme (6312973147689664409) -->
+ <skip />
+ <!-- no translation found for face_acquired_obscured (5357207702967893283) -->
+ <skip />
+ <!-- no translation found for face_acquired_sensor_dirty (2535761002815565222) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"മുഖം പരിശോധിക്കാൻ കഴിയില്ല. ഹാർഡ്വെയർ ലഭ്യമല്ല."</string>
@@ -2028,4 +2031,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ഫയൽ</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"നേരിട്ടുള്ള പങ്കിടൽ ലഭ്യമല്ല"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"ആപ്പുകളുടെ ലിസ്റ്റ്"</string>
</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 9c1c4ee..70e46b4 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -296,7 +296,7 @@
<string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"дуу хураах"</string>
<string name="permgrouprequest_microphone" msgid="9167492350681916038">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>-д аудио бичихийг зөвшөөрөх үү?"</string>
- <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Биеийн дасгал хөдөлгөөн"</string>
+ <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Дасгал хөдөлгөөн"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"таны биеийн дасгал хөдөлгөөнд хандах"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>-д таны биеийн дасгал хөдөлгөөнд хандахыг зөвшөөрөх үү?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Камер"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Нүүрээ дахин бүртгүүлнэ үү."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Царайг таних боломжгүй боллоо. Дахин оролдоно уу."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Хэт адилхан байгаа тул байрлалаа өөрчилнө үү."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Дэлгэц рүү аль болох эгц харна уу."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Дэлгэц рүү аль болох эгц харна уу."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Толгойгоо босоо чиглэлд тэгшилнэ үү."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Толгой болон утасныхаа хоорондох зайг тохируулна уу."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Камераа цэвэрлэнэ үү."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Толгойгоо арай багаар эргүүлнэ үү."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Толгойгоо арай багаар эргүүлнэ үү."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Толгойгоо арай багаар эргүүлнэ үү."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Таны нүүрийг далдалж буй аливаа зүйлийг хасна уу."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Дэлгэцийн дээд ирмэгт байрлах мэдрэгчийг цэвэрлэнэ үү."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Царайг бататгаж чадсангүй. Техник хангамж боломжгүй байна."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> файл</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Шууд хуваалцах боломжгүй"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Аппын жагсаалт"</string>
</resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index b49f0d1..9a4630c 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -51,8 +51,8 @@
<string name="needPuk2" msgid="4526033371987193070">"सिम कार्ड अनावरोधित करण्यासाठी PUK2 टाइप करा."</string>
<string name="enablePin" msgid="209412020907207950">"अयशस्वी, सिम/RUIM लॉक सुरू करा."</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
- <item quantity="one">सिम लॉक होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न उर्वरित आहे.</item>
<item quantity="other">सिम लॉक होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न उर्वरित आहेत.</item>
+ <item quantity="one">सिम लॉक होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER_0">%d</xliff:g> प्रयत्न उर्वरित आहे.</item>
</plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
@@ -176,8 +176,8 @@
<string name="low_memory" product="tv" msgid="516619861191025923">"टीव्ही संचयन भरले आहे. स्थान मोकळे करण्यासाठी काही फायली हटवा."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"फोन संचयन पूर्ण भरले आहे. स्थान मोकळे करण्यासाठी काही फायली हटवा."</string>
<plurals name="ssl_ca_cert_warning" formatted="false" msgid="5106721205300213569">
- <item quantity="one">प्रमाणपत्र अधिकार इंस्टॉल केला</item>
<item quantity="other">प्रमाणपत्र अधिकार इंस्टॉल केले</item>
+ <item quantity="one">प्रमाणपत्र अधिकार इंस्टॉल केला</item>
</plurals>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"एका अज्ञात तृतीय पक्षाद्वारे"</string>
<string name="ssl_ca_cert_noti_by_administrator" msgid="3541729986326153557">"आपल्या कार्य प्रोफाइल प्रशासकाद्वारे"</string>
@@ -235,8 +235,8 @@
<string name="bugreport_option_full_title" msgid="6354382025840076439">"संपूर्ण अहवाल"</string>
<string name="bugreport_option_full_summary" msgid="7210859858969115745">"तुमचे डिव्हाइस प्रतिसाद देत नाही किंवा खूप धीमे असते किंवा तुम्हाला सर्व अहवाल विभागांची आवश्यकता असते तेव्हा कमीतकमी सिस्टम हस्तक्षेपासाठी या पर्यायाचा वापर करा. तुम्हाला आणखी तपशील एंटर करण्याची किंवा अतिरिक्त स्क्रीनशॉट घेण्याची अनुमती देत नाही."</string>
<plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
- <item quantity="one">दोष अहवालासाठी <xliff:g id="NUMBER_1">%d</xliff:g> सेकंदामध्ये स्क्रीनशॉट घेत आहे.</item>
<item quantity="other">दोष अहवालासाठी <xliff:g id="NUMBER_1">%d</xliff:g> सेकंदांमध्ये स्क्रीनशॉट घेत आहे.</item>
+ <item quantity="one">दोष अहवालासाठी <xliff:g id="NUMBER_0">%d</xliff:g> सेकंदामध्ये स्क्रीनशॉट घेत आहे.</item>
</plurals>
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"मूक मोड"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"ध्वनी बंद आहे"</string>
@@ -301,7 +301,7 @@
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ला तुमची शारीरिक अॅक्टिव्हिटी अॅक्सेस करण्याची अनुमती द्यायची का?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"कॅमेरा"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"चित्रे घेण्याची आणि व्हिडिओ रेकॉर्ड"</string>
- <string name="permgrouprequest_camera" msgid="1299833592069671756">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ला फोटो घेऊ आणि व्हिडिओ रेकॉर्ड करू द्यायचा?"</string>
+ <string name="permgrouprequest_camera" msgid="1299833592069671756">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ला फोटो घेऊ आणि व्हिडिओ रेकॉर्ड करू द्यायचे?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"कॉल लॉग"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"फोन कॉल लॉग वाचा आणि लिहा"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ला तुमचे फोन कॉल लॉग अॅक्सेस करण्याची अनुमती द्यायची का?"</string>
@@ -412,7 +412,7 @@
<string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"हा अॅप आपल्या टीव्हीवर कॅलेंडर इव्हेंट जोडू, काढू किंवा बदलू शकतो. हा अॅप कॅलेंडर मालकांकडून येत आहेत असे वाटणारे मेसेज पाठवू किंवा त्यांच्या मालकांना सूचित केल्याशिवाय इव्हेंट बदलू शकतो."</string>
<string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"हा अॅप आपल्या फोनवर कॅलेंडर इव्हेंट जोडू, काढू किंवा बदलू शकतो. हा अॅप कॅलेंडर मालकांकडून येत आहेत असे वाटणारे मेसेज पाठवू किंवा त्यांच्या मालकांना सूचित केल्याशिवाय इव्हेंट बदलू शकतो."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"अतिरिक्त स्थान प्रदाता आदेश अॅक्सेस करा"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"अॅपला अतिरिक्त स्थान प्रदाता आदेशावर प्रवेश करण्याची अनुमती देते. हे कदाचित अॅपला GPS किंवा इतर स्थान स्त्रोत च्या ऑपरेशनमध्ये हस्तक्षेप करण्याची अनुमती देऊ शकते."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"अॅपला अतिरिक्त स्थान प्रदाता आदेशावर प्रवेश करण्याची अनुमती देते. हे कदाचित अॅपला GPS किंवा इतर स्थान स्रोत च्या ऑपरेशनमध्ये हस्तक्षेप करण्याची अनुमती देऊ शकते."</string>
<string name="permlab_accessFineLocation" msgid="6265109654698562427">"फक्त फोरग्राउंडमध्ये अचूकपणे अॅक्सेस करा"</string>
<string name="permdesc_accessFineLocation" msgid="3520508381065331098">"हे अॅप फक्त फोरग्राउंडमध्ये असतानाच तुमचे अचूक स्थान मिळवू शकते. या स्थान सेवा सुरू करणे आणि त्या वापरण्यासाठी अॅपसाठी तुमच्या फोनवर उपलब्ध करणे आवश्यक आहे, यामुळे बॅटरी वापर वाढू शकतो."</string>
<string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"फक्त फोरग्राउंडमध्ये अंदाजे स्थान (नेटवर्क आधारित) अॅक्सेस करा"</string>
@@ -571,11 +571,14 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"कृपया तुमच्या चेहऱ्याची पुन्हा नोंदणी करा."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"चेहरा ओळखू शकत नाही. पुन्हा प्रयत्न करा."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"एकाच प्रकारची पोझ देत आहात कृपया तुमची पोझ बदला."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"कृपया स्क्रीनकडे आणखी थेट पहा."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"कृपया स्क्रीनकडे आणखी थेट पहा."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"कृपया तुमची मान वर करा."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"तुमचे डोके आणि फोन यांमधली जागा मोकळी करा."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"कृपया कॅमेरा साफ करा."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"तुमचे डोके थोडे कमी फिरवा."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"तुमचे डोके थोडे कमी फिरवा."</string>
+ <!-- no translation found for face_acquired_roll_too_extreme (6312973147689664409) -->
+ <skip />
+ <!-- no translation found for face_acquired_obscured (5357207702967893283) -->
+ <skip />
+ <!-- no translation found for face_acquired_sensor_dirty (2535761002815565222) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"चेहरा पडताळू शकत नाही. हार्डवेअर उपलब्ध नाही."</string>
@@ -972,8 +975,8 @@
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 महिन्यापूर्वी"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1 महिन्यापूर्वी"</string>
<plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
- <item quantity="one">अंतिम <xliff:g id="COUNT_1">%d</xliff:g> दिवस</item>
<item quantity="other">अंतिम <xliff:g id="COUNT_1">%d</xliff:g> दिवस</item>
+ <item quantity="one">अंतिम <xliff:g id="COUNT_0">%d</xliff:g> दिवस</item>
</plurals>
<string name="last_month" msgid="3959346739979055432">"अंतिम महिना"</string>
<string name="older" msgid="5211975022815554840">"अधिक जुने"</string>
@@ -994,68 +997,68 @@
<string name="years" msgid="6881577717993213522">"वर्षे"</string>
<string name="now_string_shortest" msgid="8912796667087856402">"आत्ता"</string>
<plurals name="duration_minutes_shortest" formatted="false" msgid="3957499975064245495">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>मि</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>मि</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>मि</item>
</plurals>
<plurals name="duration_hours_shortest" formatted="false" msgid="3552182110578602356">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>ता</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>ता</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>ता</item>
</plurals>
<plurals name="duration_days_shortest" formatted="false" msgid="5213655532597081640">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>दि</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>दि</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>दि</item>
</plurals>
<plurals name="duration_years_shortest" formatted="false" msgid="7848711145196397042">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>व</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>व</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>व</item>
</plurals>
<plurals name="duration_minutes_shortest_future" formatted="false" msgid="3277614521231489951">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>मि मध्ये</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>मि मध्ये</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>मि मध्ये</item>
</plurals>
<plurals name="duration_hours_shortest_future" formatted="false" msgid="2152452368397489370">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>ता मध्ये</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>ता मध्ये</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>ता मध्ये</item>
</plurals>
<plurals name="duration_days_shortest_future" formatted="false" msgid="8088331502820295701">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>दि मध्ये</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>दि मध्ये</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>दि मध्ये</item>
</plurals>
<plurals name="duration_years_shortest_future" formatted="false" msgid="2317006667145250301">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>व मध्ये</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>व मध्ये</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>व मध्ये</item>
</plurals>
<plurals name="duration_minutes_relative" formatted="false" msgid="3178131706192980192">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> मिनिटापूर्वी</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> मिनिटांंपूर्वी</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> मिनिटापूर्वी</item>
</plurals>
<plurals name="duration_hours_relative" formatted="false" msgid="676894109982008411">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> तासापूर्वी</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> तासांंपूर्वी</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> तासापूर्वी</item>
</plurals>
<plurals name="duration_days_relative" formatted="false" msgid="2203515825765397130">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> दिवसापूर्वी</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> दिवसांंपूर्वी</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> दिवसापूर्वी</item>
</plurals>
<plurals name="duration_years_relative" formatted="false" msgid="4820062134188885734">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> वर्षापूर्वी</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> वर्षांपूर्वी</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> वर्षापूर्वी</item>
</plurals>
<plurals name="duration_minutes_relative_future" formatted="false" msgid="4655043589817680966">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> मिनिटात</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> मिनिटांमध्ये</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> मिनिटात</item>
</plurals>
<plurals name="duration_hours_relative_future" formatted="false" msgid="8084579714205223891">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> तासामध्ये</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> तासांंमध्ये</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> तासामध्ये</item>
</plurals>
<plurals name="duration_days_relative_future" formatted="false" msgid="333215369363433992">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> दिवसात</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> दिवसांंमध्ये</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> दिवसात</item>
</plurals>
<plurals name="duration_years_relative_future" formatted="false" msgid="8644862986413104011">
- <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> वर्षात</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> वर्षांंमध्ये</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> वर्षात</item>
</plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"व्हिडिओ समस्या"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"या डिव्हाइसवर प्रवाहित करण्यासाठी हा व्हिडिओ वैध नाही."</string>
@@ -1119,7 +1122,7 @@
<string name="no" msgid="5141531044935541497">"रद्द करा"</string>
<string name="dialog_alert_title" msgid="2049658708609043103">"लक्ष द्या"</string>
<string name="loading" msgid="7933681260296021180">"लोड करत आहे..."</string>
- <string name="capital_on" msgid="1544682755514494298">"चालू"</string>
+ <string name="capital_on" msgid="1544682755514494298">"सुरू"</string>
<string name="capital_off" msgid="6815870386972805832">"बंद"</string>
<string name="whichApplication" msgid="4533185947064773386">"याचा वापर करून क्रिया पूर्ण करा"</string>
<string name="whichApplicationNamed" msgid="8260158865936942783">"%1$s वापरून क्रिया पूर्ण करा"</string>
@@ -1234,12 +1237,12 @@
<string name="ringtone_picker_title_notification" msgid="4837740874822788802">"सूचना ध्वनी"</string>
<string name="ringtone_unknown" msgid="3914515995813061520">"अज्ञात"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
- <item quantity="one">वाय-फाय नेटवर्क उपलब्ध</item>
<item quantity="other">वाय-फाय नेटवर्क उपलब्ध</item>
+ <item quantity="one">वाय-फाय नेटवर्क उपलब्ध</item>
</plurals>
<plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
- <item quantity="one">खुले वाय-फाय नेटवर्क उपलब्ध</item>
<item quantity="other">खुले वाय-फाय नेटवर्क उपलब्ध</item>
+ <item quantity="one">खुले वाय-फाय नेटवर्क उपलब्ध</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"खुल्या वाय-फाय नेटवर्कशी कनेक्ट करा"</string>
<string name="wifi_available_carrier_network_title" msgid="4527932626916527897">"वाहक वाय-फाय नेटवर्कशी कनेक्ट करा"</string>
@@ -1340,7 +1343,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ठीक"</string>
<string name="usb_charging_notification_title" msgid="1595122345358177163">"हे डिव्हाइस USB ने चार्ज करत आहे"</string>
<string name="usb_supplying_notification_title" msgid="4631045789893086181">"USB ने चार्ज करायला ठेवलेले डिव्हाइस"</string>
- <string name="usb_mtp_notification_title" msgid="4238227258391151029">"USB फाइल ट्रांसफर चालू केले"</string>
+ <string name="usb_mtp_notification_title" msgid="4238227258391151029">"USB फाइल ट्रान्सफर चालू केले"</string>
<string name="usb_ptp_notification_title" msgid="5425857879922006878">"USB मार्फत PTP चालू केले"</string>
<string name="usb_tether_notification_title" msgid="3716143122035802501">"USB टेदरिंग चालू केले"</string>
<string name="usb_midi_notification_title" msgid="5356040379749154805">"USB मार्फत MIDI चालू केले"</string>
@@ -1401,7 +1404,7 @@
<string name="ext_media_missing_message" msgid="4012389235250987930">"डिव्हाइस पुन्हा घाला"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g> हलवित आहे"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"डेटा हलवित आहे"</string>
- <string name="ext_media_move_success_title" msgid="7863652232242276066">"आशय ट्रांसफर झाला आहे"</string>
+ <string name="ext_media_move_success_title" msgid="7863652232242276066">"आशय ट्रान्सफर झाला आहे"</string>
<string name="ext_media_move_success_message" msgid="8939137931961728009">"<xliff:g id="NAME">%s</xliff:g> वर आशय हलवला आहे"</string>
<string name="ext_media_move_failure_title" msgid="1604422634177382092">"आशय हलवू शकलो नाही"</string>
<string name="ext_media_move_failure_message" msgid="7388950499623016135">"पुन्हा आशय हलवून पहा"</string>
@@ -1481,8 +1484,8 @@
<string name="no_matches" msgid="8129421908915840737">"कोणत्याही जुळण्या नाहीत"</string>
<string name="find_on_page" msgid="1946799233822820384">"पेजवर शोधा"</string>
<plurals name="matches_found" formatted="false" msgid="1210884353962081884">
- <item quantity="one"><xliff:g id="TOTAL">%d</xliff:g> पैकी <xliff:g id="INDEX">%d</xliff:g></item>
<item quantity="other"><xliff:g id="TOTAL">%d</xliff:g> पैकी <xliff:g id="INDEX">%d</xliff:g></item>
+ <item quantity="one">1 जुळणी</item>
</plurals>
<string name="action_mode_done" msgid="7217581640461922289">"पूर्ण केले"</string>
<string name="progress_erasing" msgid="2569962663843586562">"शेअर केलेले स्टोरेज मिटवत आहे…"</string>
@@ -1597,7 +1600,7 @@
<string name="media_route_button_content_description" msgid="591703006349356016">"कास्ट करा"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"डिव्हाइसला कनेक्ट करा"</string>
<string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"डिव्हाइसवर स्क्रीन कास्ट करा"</string>
- <string name="media_route_chooser_searching" msgid="4776236202610828706">"डिव्हाइसेस शोधत आहे…"</string>
+ <string name="media_route_chooser_searching" msgid="4776236202610828706">"डिव्हाइस शोधत आहे…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"सेटिंग्ज"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"डिस्कनेक्ट करा"</string>
<string name="media_route_status_scanning" msgid="7279908761758293783">"स्कॅन करत आहे..."</string>
@@ -1617,8 +1620,8 @@
<string name="kg_wrong_password" msgid="2333281762128113157">"चुकीचा पासवर्ड"</string>
<string name="kg_wrong_pin" msgid="1131306510833563801">"चुकीचा पिन"</string>
<plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="8790651267324125694">
- <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> सेकंदात पुन्हा प्रयत्न करा.</item>
<item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> सेकंदांत पुन्हा प्रयत्न करा.</item>
+ <item quantity="one">एका सेकंदात पुन्हा प्रयत्न करा.</item>
</plurals>
<string name="kg_pattern_instructions" msgid="398978611683075868">"तुमचा पॅटर्न काढा"</string>
<string name="kg_sim_pin_instructions" msgid="2319508550934557331">"सिम पिन एंटर करा"</string>
@@ -1775,8 +1778,8 @@
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"पिन जुळत नाहीत. पुन्हा प्रयत्न करा."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"पिन खूप लहान आहे. किमान 4 अंकांचा असणे आवश्यक आहे."</string>
<plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
- <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> सेकंदात पुन्हा प्रयत्न करा</item>
<item quantity="other"><xliff:g id="COUNT">%d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा</item>
+ <item quantity="one">1 सेकंदात पुन्हा प्रयत्न करा</item>
</plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"नंतर पुन्हा प्रयत्न करा"</string>
<string name="immersive_cling_title" msgid="8394201622932303336">"पूर्ण स्क्रीनवर पाहत आहात"</string>
@@ -1800,42 +1803,42 @@
<string name="package_updated_device_owner" msgid="1847154566357862089">"आपल्या प्रशासकाने अपडेट केले"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"आपल्या प्रशासकाने हटवले"</string>
<string name="confirm_battery_saver" msgid="639106420541753635">"ओके"</string>
- <string name="battery_saver_description_with_learn_more" msgid="2108984221113106294">"बॅटरी लाइफ वाढवण्यासाठी बॅटरी सेव्हर बॅकग्राउंड अॅक्टिव्हिटी, काही व्हिज्युअल इफेक्ट आणि इतर हाय-पॉवर वैशिष्ट्ये बंद किंवा मर्यादित करतो. "<annotation id="url">"अधिक जाणून घ्या"</annotation></string>
+ <string name="battery_saver_description_with_learn_more" msgid="2108984221113106294">"बॅटरी सेव्हर हे वैशिष्ट्य बॅटरीचे आयुष्य वाढवण्यासाठी बॅकग्राउंड अॅक्टिव्हिटी, काही व्हिज्युअल इफेक्ट आणि इतर हाय-पॉवर वैशिष्ट्ये बंद किंवा मर्यादित करते. "<annotation id="url">"अधिक जाणून घ्या"</annotation></string>
<string name="battery_saver_description" msgid="6413346684861241431">"बॅटरी लाइफ वाढवण्यासाठी बॅटरी सेव्हर बॅकग्राउंड अॅक्टिव्हिटी, काही व्हिज्युअल इफेक्ट आणि इतर हाय-पॉवर वैशिष्ट्ये बंद किंवा मर्यादित करतो."</string>
- <string name="data_saver_description" msgid="6015391409098303235">"डेटा वापर कमी करण्यात मदत करण्यासाठी, डेटा सर्व्हर काही अॅप्सना पार्श्वभूमीमध्ये डेटा पाठविण्यास किंवा मिळवण्यास प्रतिबंध करतो. तुम्ही सध्या वापरत असलेला अॅप डेटामध्ये प्रवेश करू शकतो परंतु तसे तो खूप कमी वेळा करू शकतो. याचा अर्थ, उदाहरणार्थ, तुम्ही इमेज टॅप करेपर्यंत त्या प्रदर्शित करणार नाहीत असा असू शकतो."</string>
- <string name="data_saver_enable_title" msgid="4674073932722787417">"डेटा बचतकर्ता चालू करायचा?"</string>
+ <string name="data_saver_description" msgid="6015391409098303235">"डेटा सर्व्हर डेटाचा वापर कमी करण्यात मदत करण्यासाठी काही अॅप्सना पार्श्वभूमीमध्ये डेटा पाठवण्यास किंवा मिळवण्यास प्रतिबंध करतो. तुम्ही सध्या वापरत असलेले अॅप डेटा अॅक्सेस करू शकते, पण तसे खूप कमी वेळा होते. याचाच अर्थ असा की, तुम्ही इमेजवर टॅप करेपर्यंत त्या डिस्प्ले होणार नाहीत असा असू शकतो."</string>
+ <string name="data_saver_enable_title" msgid="4674073932722787417">"डेटा सेव्हर चालू करायचा?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"चालू करा"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
- <item quantity="one">%1$d मिनिटासाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
<item quantity="other">%1$d मिनिटांसाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
+ <item quantity="one">एका मिनिटासाठी (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> पर्यंत)</item>
</plurals>
<plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="6830154222366042597">
- <item quantity="one">%1$d मिनिटासाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
<item quantity="other">%1$d मिनिटासाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
+ <item quantity="one">1 मिनिटासाठी (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> पर्यंत)</item>
</plurals>
<plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="736789408293052283">
- <item quantity="one">%1$d तासासाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
<item quantity="other">%1$d तासांसाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
+ <item quantity="one">एका तासासाठी (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> पर्यंत)</item>
</plurals>
<plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="4787552595253082371">
- <item quantity="one">%1$d तासासाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
<item quantity="other">%1$d तासासाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
+ <item quantity="one">1 तासासाठी (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> पर्यंत)</item>
</plurals>
<plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
- <item quantity="one">%d मिनिटासाठी</item>
<item quantity="other">%d मिनिटांसाठी</item>
+ <item quantity="one">एक मिनिटासाठी</item>
</plurals>
<plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2199350154433426128">
- <item quantity="one">%d मिनिटासाठी</item>
<item quantity="other">%d मिनिटांसाठी</item>
+ <item quantity="one">1 मिनिटासाठी</item>
</plurals>
<plurals name="zen_mode_duration_hours" formatted="false" msgid="6571961796799076730">
- <item quantity="one">%d तासासाठी</item>
<item quantity="other">%d तासांसाठी</item>
+ <item quantity="one">एक तासासाठी</item>
</plurals>
<plurals name="zen_mode_duration_hours_short" formatted="false" msgid="6748277774662434217">
- <item quantity="one">%d तासासाठी</item>
<item quantity="other">%d तासासाठी</item>
+ <item quantity="one">1 तासासाठी</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> पर्यंत"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> पर्यंत (पुढील अलार्म)"</string>
@@ -1874,8 +1877,8 @@
<string name="close_button_text" msgid="3937902162644062866">"बंद करा"</string>
<string name="notification_messaging_title_template" msgid="3452480118762691020">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
<plurals name="selected_count" formatted="false" msgid="7187339492915744615">
- <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> निवडला</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> निवडले</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> निवडला</item>
</plurals>
<string name="default_notification_channel_label" msgid="5929663562028088222">"वर्गीकरण न केलेले"</string>
<string name="importance_from_user" msgid="7318955817386549931">"तुम्ही या सूचनांचे महत्त्व सेट केले."</string>
@@ -1935,8 +1938,8 @@
<string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"सामग्रींची स्वयं-भरणा करता येणार नाही"</string>
<string name="autofill_picker_no_suggestions" msgid="3908514303773350735">"आपोआप भरण्याच्या कोणत्याही सूचना नाहीत"</string>
<plurals name="autofill_picker_some_suggestions" formatted="false" msgid="5506565809835815274">
- <item quantity="one">आपोआप भरण्याची <xliff:g id="COUNT">%1$s</xliff:g> सूचना</item>
<item quantity="other">आपोआप भरण्याच्या <xliff:g id="COUNT">%1$s</xliff:g> सूचना</item>
+ <item quantity="one">आपोआप भरण्याची एक सूचना</item>
</plurals>
<string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" मध्ये सेव्ह करायचे का?"</string>
<string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g>, "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" मध्ये सेव्ह करायचे का?"</string>
@@ -2024,8 +2027,9 @@
<string name="mime_type_presentation_ext" msgid="2982650207774823437">"<xliff:g id="EXTENSION">%1$s</xliff:g> सादरीकरण"</string>
<string name="car_loading_profile" msgid="3545132581795684027">"लोड होत आहे"</string>
<plurals name="file_count" formatted="false" msgid="1628600959752419449">
- <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> फाइल</item>
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> फायली</item>
+ <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> फाइल</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"थेट शेअर करणे उपलब्ध नाही"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"अॅप्स सूची"</string>
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 1faf01d..65e2431 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Sila daftarkan semula wajah anda."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Tidak lagi dapat mengecam wajah. Cuba lagi."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Terlalu serupa, sila ubah lagak gaya anda."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Sila lihat terus pada skrin."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Sila lihat terus pada skrin."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Sila tegakkan kepala anda."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Kosongkan ruang di antara kepala anda dgn telefon."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Sila bersihkan kamera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Pusingkan kepala anda kurang sedikit."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Pusingkan kepala anda kurang sedikit."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Pusingkan kepala anda kurang sedikit."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Alih keluar apa saja yang melindungi wajah anda."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Bersihkan penderia di tepi bahagian atas skrin."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Tdk dpt sahkan wajah. Perkakasan tidak tersedia."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> fail</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Perkongsian langsung tidak tersedia"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Senarai apl"</string>
</resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index a2a924c..f3f077b 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -302,7 +302,7 @@
<string name="permgrouplab_camera" msgid="4820372495894586615">"ကင်မရာ"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"ဓာတ်ပုံ ရိုက်ပြီးနောက် ဗွီဒီယို မှတ်တမ်းတင်ရန်"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> အား ဓာတ်ပုံနှင့် ဗီဒီယိုရိုက်ကူးခွင့် ပေးလိုပါသလား။"</string>
- <string name="permgrouplab_calllog" msgid="8798646184930388160">"ခေါ်ဆိုထားသော မှတ်တမ်းများ"</string>
+ <string name="permgrouplab_calllog" msgid="8798646184930388160">"ခေါ်ဆိုမှတ်တမ်း"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"ဖုန်းခေါ်ဆိုထားသော မှတ်တမ်း ဖတ်ပြီး ရေးရန်"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> အား သင်၏ခေါ်ဆိုထားသော မှတ်တမ်းများကို သုံးခွင့်ပေးလိုပါသလား။"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"ဖုန်း"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"သင့်မျက်နှာကို ပြန်စာရင်းသွင်းပါ။"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"မျက်နှာ မမှတ်သားနိုင်တော့ပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"ဆင်တူနေသည်၊ အမူအရာ ပြောင်းပါ။"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"ဖန်သားပြင်ကို တည့်တည့်ကြည့်ပါ။"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"ဖန်သားပြင်ကို တည့်တည့်ကြည့်ပါ။"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"ခေါင်းမတ်မတ်ထားပါ။"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"သင့်မျက်နှာနှင့် ဖုန်းအကြား ဘာမှကွယ်မထားပါနှင့်။"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"ကင်မရာကို သန့်ရှင်းရေးလုပ်ပါ။"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"ခေါင်းကို သိပ်မလှည့်ပါနှင့်။"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ခေါင်းကို သိပ်မလှည့်ပါနှင့်။"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ခေါင်းကို သိပ်မလှည့်ပါနှင့်။"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"သင့်မျက်နှာကို ကွယ်နေသည့်အရာအားလုံး ဖယ်ပါ။"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"မျက်နှာပြင်ထိပ်ရှိ အာရုံခံဆင်ဆာကို သန့်ရှင်းပါ။"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"မျက်နှာကို အတည်ပြု၍ မရပါ။ ဟာ့ဒ်ဝဲ မရနိုင်ပါ။"</string>
@@ -2028,4 +2028,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ဖိုင်</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"တိုက်ရိုက်မျှဝေ၍ မရပါ"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"အက်ပ်စာရင်း"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index ff38cae..5ca5d94 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -296,7 +296,7 @@
<string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"ta opp lyd"</string>
<string name="permgrouprequest_microphone" msgid="9167492350681916038">"Vil du la <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ta opp lyd?"</string>
- <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Fysisk aktivitet"</string>
+ <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Fysisk aktivitet-"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"tilgang til den fysiske aktiviteten din"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"Vil du gi <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> tilgang til den fysiske aktiviteten din?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
@@ -342,7 +342,7 @@
<string name="permlab_receiveMms" msgid="1821317344668257098">"motta tekstmeldinger (MMS)"</string>
<string name="permdesc_receiveMms" msgid="533019437263212260">"Lar appen motta og behandle multimediemeldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din uten at du har sett dem."</string>
<string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lese kringkastede meldinger"</string>
- <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillater at appen kan lese kringkastede meldinger enheten din mottar. Kringkastede varsler leveres noen steder for å advare deg om nødsituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
+ <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillater at appen kan lese kringkastede meldinger enheten din mottar. Kringkastede varsler leveres noen steder for å advare deg om nødssituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lese abonnement på nyhetskilder"</string>
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Lar appen hente inn detaljer om strømmer som er synkroniserte for øyeblikket."</string>
<string name="permlab_sendSms" msgid="7544599214260982981">"sende og lese SMS-meldinger"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registrer ansiktet ditt på nytt."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Kan ikke gjenkjenne ansiktet lenger. Prøv igjen."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"For likt – endre posituren din."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Se mer direkte på skjermen."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Se mer direkte på skjermen."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Rett hodet ditt vertikalt."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Tøm området mellom hodet ditt og telefonen."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Rengjør kameraet."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Vri hodet ditt litt mindre."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Vri hodet ditt litt mindre."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Vri hodet ditt litt mindre."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Fjern alt som skjuler ansiktet ditt."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Rengjør sensoren på toppkanten av skjermen."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Kan ikke bekrefte ansikt. Utilgjengelig maskinvare."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> fil</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Direktedeling er ikke tilgjengelig"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Appliste"</string>
</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 09fe51c..aa99610 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -416,9 +416,9 @@
<string name="permlab_accessFineLocation" msgid="6265109654698562427">"अग्रभूमिमा मात्र सटीक स्थानमाथि पहुँच राख्नुहोस्"</string>
<string name="permdesc_accessFineLocation" msgid="3520508381065331098">"यो अनुप्रयोगले अग्रभागमा चलिरहेको अवस्थामा मात्र तपाईंलाई स्थानको सटिक जानकारी दिन सक्छ। यी स्थानसम्बन्धी सेवाहरू अनिवार्य रूपमा सक्रिय गरिएका हुनु पर्छ र अनुप्रयोगले यिनीहरूको प्रयोग गर्न सकोस् भन्नाका खातिर तपाईंको फोनमै उपलब्ध हुन्छन्। यस कार्यले गर्दा ब्याट्री बढी खर्च हुन सक्छ।"</string>
<string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"अग्रभूमिमा मात्र अनुमानित स्थान (नेटवर्कमा आधारित) माथि पहुँच राख्नुहोस्"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको ट्याब्लेटमा उपलब्ध हुनु पर्छ।"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको TV मा उपलब्ध हुनु पर्छ।"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको फोनमा उपलब्ध हुनु पर्छ।"</string>
+ <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थानसम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको ट्याब्लेटमा उपलब्ध हुनु पर्छ।"</string>
+ <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थानसम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको TV मा उपलब्ध हुनु पर्छ।"</string>
+ <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थानसम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको फोनमा उपलब्ध हुनु पर्छ।"</string>
<string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"पृष्ठभूमिमा स्थानसम्बन्धी पहुँच"</string>
<string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"यसका अतिरिक्त यसलाई अनुमानित वा सटिक स्थानमाथि पहुँच राख्ने अनुमति दिइएको छ भने उक्त अनुप्रयोगले पृष्ठभूमिमा चलिरहेको बेला स्थानमाथि पहुँच राख्न सक्छ।"</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"तपाईँका अडियो सेटिङहरू परिवर्तन गर्नुहोस्"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"कृपया आफ्नो अनुहार पुनः दर्ता गर्नुहोस्।"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"अब उप्रान्त अनुहार पहिचान गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"अनुहार उस्तै भयो, कृपया आफ्नो पोज बदल्नुहोस्।"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"कृपया अझ सीधा गरी स्क्रिनमा हेर्नुहोस्।"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"कृपया अझ सीधा गरी स्क्रिनमा हेर्नुहोस्।"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"कृपया आफ्नो अनुहार ठाडो रूपमा सीधा पार्नुहोस्।"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"आफ्नो टाउको र फोनका बिचको स्थान हटाउनुहोस्।"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"कृपया क्यामेरा सफा गर्नुहोस्।"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"आफ्नो टाउको अलि थोरै घुमाउनुहोस्।"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"आफ्नो टाउको अलि थोरै घुमाउनुहोस्।"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"आफ्नो टाउको अलि थोरै घुमाउनुहोस्।"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"तपाईंको अनुहार लुकाउने सबै कुरा लुकाउनुहोस्।"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"स्क्रिनको शीर्ष कुनामा रहेको सेन्सर सफा गर्नुहोस्।"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"अनुहार पुष्टि गर्न सकिएन। हार्डवेयर उपलब्ध छैन।"</string>
@@ -1026,8 +1026,8 @@
<item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>वर्षमा</item>
</plurals>
<plurals name="duration_minutes_relative" formatted="false" msgid="3178131706192980192">
- <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> मिनेट अघि</item>
- <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> मिनेट अघि</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> मिनेटअघि</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> मिनेटअघि</item>
</plurals>
<plurals name="duration_hours_relative" formatted="false" msgid="676894109982008411">
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> घन्टा अघि</item>
@@ -2033,4 +2033,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> फाइल</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"सीधै आदान प्रदान गर्ने सुविधा उपलब्ध छैन"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"अनुप्रयोगहरूको सूची"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index ff6e310..61ffafc 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -302,9 +302,9 @@
<string name="permgrouplab_camera" msgid="4820372495894586615">"Camera"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"foto\'s maken en video opnemen"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> toestaan om foto\'s te maken en video op te nemen?"</string>
- <string name="permgrouplab_calllog" msgid="8798646184930388160">"Gesprekkenlijsten"</string>
- <string name="permgroupdesc_calllog" msgid="3006237336748283775">"gesprekkenlijst lezen en schrijven"</string>
- <string name="permgrouprequest_calllog" msgid="8487355309583773267">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> toegang geven tot je gesprekkenlijsten?"</string>
+ <string name="permgrouplab_calllog" msgid="8798646184930388160">"Gesprekslijsten"</string>
+ <string name="permgroupdesc_calllog" msgid="3006237336748283775">"gesprekslijst lezen en schrijven"</string>
+ <string name="permgrouprequest_calllog" msgid="8487355309583773267">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> toegang geven tot je gesprekslijsten?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Telefoon"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"telefoneren en gesprekken beheren"</string>
<string name="permgrouprequest_phone" msgid="9166979577750581037">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> toestaan om telefoongesprekken te starten en te beheren?"</string>
@@ -395,12 +395,12 @@
<string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Hiermee kan de app gegevens wijzigen over de contacten die zijn opgeslagen op je tablet, inclusief de frequentie waarmee je hebt gebeld, gemaild of op andere manieren hebt gecommuniceerd met specifieke contacten. Met deze toestemming kunnen apps contactgegevens verwijderen."</string>
<string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Hiermee kan de app gegevens wijzigen over de contacten die zijn opgeslagen op je tv, inclusief de frequentie waarmee je hebt gebeld, gemaild of op andere manieren hebt gecommuniceerd met specifieke contacten. Met deze toestemming kunnen apps contactgegevens verwijderen."</string>
<string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Hiermee kan de app gegevens wijzigen over de contacten die zijn opgeslagen op je telefoon, inclusief de frequentie waarmee je hebt gebeld, gemaild of op andere manieren hebt gecommuniceerd met specifieke contacten. Met deze toestemming kunnen apps contactgegevens verwijderen."</string>
- <string name="permlab_readCallLog" msgid="3478133184624102739">"gesprekkenlijst lezen"</string>
+ <string name="permlab_readCallLog" msgid="3478133184624102739">"gesprekslijst lezen"</string>
<string name="permdesc_readCallLog" msgid="3204122446463552146">"Deze app kan je gespreksgeschiedenis lezen."</string>
- <string name="permlab_writeCallLog" msgid="8552045664743499354">"gesprekkenlijst schrijven"</string>
- <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Toestaan dat de app de gesprekkenlijst van je tablet aanpast, waaronder gegevens over inkomende en uitgaande gesprekken. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen."</string>
- <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Toestaan dat de app de gesprekkenlijst van je tv aanpast, waaronder gegevens over inkomende en uitgaande gesprekken. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen."</string>
- <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Toestaan dat de app de gesprekkenlijst van je telefoon aanpast, waaronder gegevens over inkomende en uitgaande gesprekken. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen."</string>
+ <string name="permlab_writeCallLog" msgid="8552045664743499354">"gesprekslijst schrijven"</string>
+ <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Toestaan dat de app de gesprekslijst van je tablet aanpast, waaronder gegevens over inkomende en uitgaande gesprekken. Schadelijke apps kunnen hiermee je gesprekslijst wissen of aanpassen."</string>
+ <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Toestaan dat de app de gesprekslijst van je tv aanpast, waaronder gegevens over inkomende en uitgaande gesprekken. Schadelijke apps kunnen hiermee je gesprekslijst wissen of aanpassen."</string>
+ <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Toestaan dat de app de gesprekslijst van je telefoon aanpast, waaronder gegevens over inkomende en uitgaande gesprekken. Schadelijke apps kunnen hiermee je gesprekslijst wissen of aanpassen."</string>
<string name="permlab_bodySensors" msgid="4683341291818520277">"toegang tot lichaamssensoren (zoals hartslagmeters)"</string>
<string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Hiermee kan de app toegang krijgen tot gegevens van sensoren die je lichamelijke conditie controleren, zoals je hartslag."</string>
<string name="permlab_readCalendar" msgid="6716116972752441641">"Agenda-afspraken en -gegevens lezen"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registreer je gezicht opnieuw."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Herkent gezicht niet meer. Probeer het nog eens."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Lijkt te veel op elkaar. Verander je pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Kijk rechter naar het scherm."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Kijk rechter naar het scherm."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Houd je hoofd verticaal recht."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Zorg dat er niks tussen je hoofd en telefoon zit."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Maak de camera schoon."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Draai je hoofd iets minder."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Draai je hoofd iets minder."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Draai je hoofd iets minder."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Zorg dat je gezicht volledig zichtbaar is."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Maak de sensor bovenaan het scherm schoon."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Kan gezicht niet verifiëren. Hardware niet beschikbaar."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> bestand</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Rechtstreeks delen is niet beschikbaar"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lijst met apps"</string>
</resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index c66fba1..731f2d0 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -571,11 +571,14 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"ଦୟାକରି ଆପଣଙ୍କର ମୁହଁ ପୁଣି-ଏନ୍ରୋଲ୍ କରନ୍ତୁ।"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"ଆଉ ମୁହଁ ଚିହ୍ନଟ କରିହେଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"ଅତ୍ୟନ୍ତ ସମପରି, ଦୟାକରି ଆପଣଙ୍କର ପୋଜ୍ ବଦଳାନ୍ତୁ।"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"ଦୟାକରି ସ୍କ୍ରିନ୍କୁ ସିଧା ଦେଖନ୍ତୁ।"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"ଦୟାକରି ସ୍କ୍ରିନ୍କୁ ସିଧା ଦେଖନ୍ତୁ।"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"ଦୟାକରି ଆପଣଙ୍କର ମୁଣ୍ଡକୁ ସିଧା ରଖନ୍ତୁ।"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"ଆପଣଙ୍କର ମୁଣ୍ଡ ଏବଂ ଫୋନ୍ ମଧ୍ୟରେ ଥିବା ସ୍ଥାନ କମ୍ କରନ୍ତୁ।"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"ଦୟାକରି କ୍ୟାମେରାକୁ ସଫା କରନ୍ତୁ।"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"ଆପଣଙ୍କର ମୁଣ୍ଡକୁ ଟିକିଏ ବୁଲାନ୍ତୁ।"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ଆପଣଙ୍କର ମୁଣ୍ଡକୁ ଟିକିଏ ବୁଲାନ୍ତୁ।"</string>
+ <!-- no translation found for face_acquired_roll_too_extreme (6312973147689664409) -->
+ <skip />
+ <!-- no translation found for face_acquired_obscured (5357207702967893283) -->
+ <skip />
+ <!-- no translation found for face_acquired_sensor_dirty (2535761002815565222) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ମୁହଁ ଚିହ୍ନଟ କରିପାରିଲା ନାହିଁ। ହାର୍ଡୱେୟାର୍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
@@ -1218,7 +1221,7 @@
<string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"ରିଙ୍ଗଟୋନ୍କୁ ନିରବ ଭାବେ ସେଟ୍ କରାଯାଇଛି"</string>
<string name="volume_call" msgid="3941680041282788711">"ଇନ୍-କଲ୍ ଭଲ୍ୟୁମ୍"</string>
<string name="volume_bluetooth_call" msgid="2002891926351151534">"ବ୍ଲୁଟୂଥ୍ ଇନ୍-କଲ୍ ଭଲ୍ୟୁମ୍"</string>
- <string name="volume_alarm" msgid="1985191616042689100">"ଆଲାର୍ମର ଭଲ୍ୟୁମ୍"</string>
+ <string name="volume_alarm" msgid="1985191616042689100">"ଆଲାରାମ୍ ଭଲ୍ୟୁମ୍"</string>
<string name="volume_notification" msgid="2422265656744276715">"ବିଜ୍ଞପ୍ତି ଭଲ୍ୟୁମ୍"</string>
<string name="volume_unknown" msgid="1400219669770445902">"ଭଲ୍ୟୁମ୍"</string>
<string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"ବ୍ଲୁଟୂଥ୍ ଭଲ୍ୟୁମ୍"</string>
@@ -1595,7 +1598,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"ୱେୟାର୍ଲେସ୍ ଡିସ୍ପ୍ଲେ"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"କାଷ୍ଟ କରନ୍ତୁ"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"ଡିଭାଇସ୍ ସଂଯୋଗ କରନ୍ତୁ"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ଡିଭାଇସ୍ରେ ସ୍କ୍ରୀନ୍ କାଷ୍ଟ କରନ୍ତୁ"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ଡିଭାଇସରେ ସ୍କ୍ରିନ୍ କାଷ୍ଟ କରନ୍ତୁ"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"ଡିଭାଇସ୍ ଖୋଜାଯାଉଛି…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"ସେଟିଙ୍ଗ"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"ବିଛିନ୍ନ କରନ୍ତୁ"</string>
@@ -1814,7 +1817,7 @@
</plurals>
<plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="736789408293052283">
<item quantity="other">%1$d ଘଣ୍ଟା ପାଇଁ (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
- <item quantity="one">, 1 ଘଣ୍ଟା ପାଇଁ (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
+ <item quantity="one">1 ଘଣ୍ଟା ପାଇଁ (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
</plurals>
<plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="4787552595253082371">
<item quantity="other">%1$d ଘଣ୍ଟା ପାଇଁ (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ)</item>
@@ -1830,7 +1833,7 @@
</plurals>
<plurals name="zen_mode_duration_hours" formatted="false" msgid="6571961796799076730">
<item quantity="other">%d ଘଣ୍ଟା ପାଇଁ</item>
- <item quantity="one">, 1 ଘଣ୍ଟା ପାଇଁ</item>
+ <item quantity="one">1 ଘଣ୍ଟା ପାଇଁ</item>
</plurals>
<plurals name="zen_mode_duration_hours_short" formatted="false" msgid="6748277774662434217">
<item quantity="other">%d ଘଣ୍ଟା ପାଇଁ</item>
@@ -1884,7 +1887,7 @@
<string name="language_selection_title" msgid="2680677278159281088">"ଏକ ଭାଷା ଯୋଡ଼ନ୍ତୁ"</string>
<string name="country_selection_title" msgid="2954859441620215513">"ପସନ୍ଦର ଅଞ୍ଚଳ"</string>
<string name="search_language_hint" msgid="7042102592055108574">"ଭାଷାର ନାମ ଟାଇପ୍ କରନ୍ତୁ"</string>
- <string name="language_picker_section_suggested" msgid="8414489646861640885">"ପରାମର୍ଶିତ"</string>
+ <string name="language_picker_section_suggested" msgid="8414489646861640885">"ପ୍ରସ୍ତାବିତ"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"ସମସ୍ତ ଭାଷା"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"ସମସ୍ତ ଅଞ୍ଚଳ"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
@@ -2027,4 +2030,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g>ଟି ଫାଇଲ୍</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"ସିଧାସଳଖ ସେୟାର୍ ସୁବିଧା ଉପଲବ୍ଧ ନାହିଁ"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"ଆପ୍ସ ତାଲିକା"</string>
</resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 6aaad08..9ed1040 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -223,11 +223,11 @@
<string name="global_actions" product="tv" msgid="7240386462508182976">"TV ਚੋਣਾਂ"</string>
<string name="global_actions" product="default" msgid="2406416831541615258">"ਫ਼ੋਨ ਚੋਣਾਂ"</string>
<string name="global_action_lock" msgid="2844945191792119712">"ਸਕ੍ਰੀਨ ਲਾਕ"</string>
- <string name="global_action_power_off" msgid="4471879440839879722">"ਪਾਵਰ ਬੰਦ"</string>
+ <string name="global_action_power_off" msgid="4471879440839879722">"ਫ਼ੋਨ ਬੰਦ ਕਰੋ"</string>
<string name="global_action_emergency" msgid="7112311161137421166">"ਸੰਕਟਕਾਲ"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"ਬਗ ਰਿਪੋਰਟ"</string>
<string name="global_action_logout" msgid="935179188218826050">"ਸੈਸ਼ਨ ਸਮਾਪਤ ਕਰੋ"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਵੋ"</string>
<string name="bugreport_title" msgid="5981047024855257269">"ਬੱਗ ਰਿਪੋਰਟ"</string>
<string name="bugreport_message" msgid="398447048750350456">"ਇਹ ਇੱਕ ਈਮੇਲ ਸੁਨੇਹਾ ਭੇਜਣ ਲਈ, ਤੁਹਾਡੇ ਵਰਤਮਾਨ ਡੀਵਾਈਸ ਬਾਰੇ ਜਾਣਕਾਰੀ ਇਕੱਠੀ ਕਰੇਗਾ। ਬੱਗ ਰਿਪੋਰਟ ਸ਼ੁਰੂ ਕਰਨ ਵਿੱਚ ਥੋੜ੍ਹਾ ਸਮਾਂ ਲੱਗੇਗਾ ਜਦੋਂ ਤੱਕ ਇਹ ਭੇਜੇ ਜਾਣ ਲਈ ਤਿਆਰ ਨਾ ਹੋਵੇ, ਕਿਰਪਾ ਕਰਕੇ ਧੀਰਜ ਰੱਖੋ।"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ਅੰਤਰਕਿਰਿਆਤਮਕ ਰਿਪੋਰਟ"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"ਕਿਰਪਾ ਕਰਕੇ ਆਪਣਾ ਚਿਹਰਾ ਦੁਬਾਰਾ ਦਰਜ ਕਰੋ।"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"ਹੁਣ ਚਿਹਰਾ ਪਛਾਣਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"ਬਹੁਤ ਮਿਲਦਾ-ਜੁਲਦਾ ਹੈ, ਕਿਰਪਾ ਕਰਕੇ ਆਪਣਾ ਅੰਦਾਜ਼ ਬਦਲੋ।"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"ਕਿਰਪਾ ਕਰਕੇ ਸਿੱਧਾ ਸਕ੍ਰੀਨ ਵੱਲ ਦੇਖੋ।"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"ਕਿਰਪਾ ਕਰਕੇ ਸਿੱਧਾ ਸਕ੍ਰੀਨ ਵੱਲ ਦੇਖੋ।"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਸਿਰ ਨੂੰ ਸਿੱਧਾ ਖੜ੍ਹਵਾਂ ਰੱਖੋ।"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"ਤੁਹਾਡੇ ਸਿਰ ਅਤੇ ਫ਼ੋਨ ਵਿਚਾਲੇ ਕੁਝ ਨਾ ਹੋਵੇ।"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"ਕਿਰਪਾ ਕਰਕੇ ਕੈਮਰਾ ਸਾਫ਼ ਕਰੋ।"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"ਆਪਣਾ ਸਿਰ ਥੋੜਾ ਜਿਹਾ ਝੁਕਾਓ।"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ਆਪਣਾ ਸਿਰ ਥੋੜਾ ਜਿਹਾ ਝੁਕਾਓ।"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ਆਪਣਾ ਸਿਰ ਥੋੜਾ ਜਿਹਾ ਝੁਕਾਓ।"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"ਤੁਹਾਡਾ ਚਿਹਰਾ ਲੁਕਾਉਣ ਵਾਲੀ ਕੋਈ ਵੀ ਚੀਜ਼ ਹਟਾਓ।"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"ਸਕ੍ਰੀਨ ਦੇ ਸਿਖਰਲੇ ਕਿਨਾਰੇ ਦਾ ਸੈਂਸਰ ਸਾਫ਼ ਕਰੋ।"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ਚਿਹਰੇ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਹੋ ਸਕੀ। ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ।"</string>
@@ -1322,7 +1322,7 @@
<string name="sim_done_button" msgid="827949989369963775">"ਹੋ ਗਿਆ"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM ਕਾਰਡ ਜੋੜਿਆ ਗਿਆ"</string>
<string name="sim_added_message" msgid="6599945301141050216">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਤੱਕ ਪਹੁੰਚ ਲਈ ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਮੁੜ-ਚਾਲੂ ਕਰੋ।"</string>
- <string name="sim_restart_button" msgid="4722407842815232347">"ਰੀਸਟਾਰਟ ਕਰੋ"</string>
+ <string name="sim_restart_button" msgid="4722407842815232347">"ਮੁੜ-ਸ਼ੁਰੂ ਕਰੋ"</string>
<string name="install_carrier_app_notification_title" msgid="9056007111024059888">"ਮੋਬਾਈਲ ਸੇਵਾ ਕਿਰਿਆਸ਼ੀਲ ਕਰੋ"</string>
<string name="install_carrier_app_notification_text" msgid="3346681446158696001">"ਆਪਣੇ ਨਵੇਂ ਸਿਮ ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਕਰਨ ਲਈ ਕੈਰੀਅਰ ਐਪ ਡਾਊਨਲੋਡ ਕਰੋ"</string>
<string name="install_carrier_app_notification_text_app_name" msgid="1196505084835248137">"ਆਪਣੇ ਨਵੇਂ ਸਿਮ ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਕਰਨ ਲਈ <xliff:g id="APP_NAME">%1$s</xliff:g> ਐਪ ਡਾਊਨਲੋਡ ਕਰੋ"</string>
@@ -1596,8 +1596,8 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"ਪ੍ਰਸਾਰਿਤ ਕਰੋ"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰੋ"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ਡੀਵਾਈਸ ਨਾਲ ਸਕ੍ਰੀਨ ਜੋੜੋ"</string>
- <string name="media_route_chooser_searching" msgid="4776236202610828706">"ਡਿਵਾਈਸਾਂ ਦੀ ਖੋਜ ਕਰ ਰਿਹਾ ਹੈ…"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ਡੀਵਾਈਸ ਨਾਲ ਸਕ੍ਰੀਨ ਕਾਸਟ ਕਰੋ"</string>
+ <string name="media_route_chooser_searching" msgid="4776236202610828706">"ਡੀਵਾਈਸਾਂ ਦੀ ਖੋਜ ਹੋ ਰਹੀ ਹੈ…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"ਸੈਟਿੰਗਾਂ"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
<string name="media_route_status_scanning" msgid="7279908761758293783">"ਸਕੈਨ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..."</string>
@@ -2028,4 +2028,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ਫ਼ਾਈਲਾਂ</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"ਸਿੱਧਾ ਸਾਂਝਾ ਕਰਨ ਦੀ ਸੁਵਿਧਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"ਐਪ ਸੂਚੀ"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 8a77fd0..75bfc85 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -213,7 +213,7 @@
<string name="reboot_to_update_reboot" msgid="6428441000951565185">"Uruchamiam ponownie…"</string>
<string name="reboot_to_reset_title" msgid="4142355915340627490">"Przywracanie danych fabrycznych"</string>
<string name="reboot_to_reset_message" msgid="2432077491101416345">"Uruchamiam ponownie…"</string>
- <string name="shutdown_progress" msgid="2281079257329981203">"Wyłączanie..."</string>
+ <string name="shutdown_progress" msgid="2281079257329981203">"Wyłączam..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet zostanie wyłączony."</string>
<string name="shutdown_confirm" product="tv" msgid="476672373995075359">"Telewizor zostanie wyłączony."</string>
<string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Zegarek zostanie wyłączony."</string>
@@ -577,11 +577,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Zarejestruj swoją twarz ponownie."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Nie można już rozpoznać twarzy. Spróbuj ponownie."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Za mała różnica. Zmień pozycję."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Patrz prosto na ekran."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Patrz prosto na ekran."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Wyprostuj głowę w pionie."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Między telefonem a Twoją głową powinno być pusto."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Wyczyść aparat."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Trochę mniej obróć głowę."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Trochę mniej obróć głowę."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Trochę mniej obróć głowę."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Usuń wszystko, co zasłania Ci twarz."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Wyczyść czujnik na górnej krawędzi ekranu."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nie można zweryfikować twarzy. Sprzęt niedostępny."</string>
@@ -2099,4 +2099,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> plik</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Udostępnianie bezpośrednie jest niedostępne"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lista aplikacji"</string>
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index b572591..87c9e16 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -228,7 +228,7 @@
<string name="global_action_bug_report" msgid="7934010578922304799">"Relatório de bugs"</string>
<string name="global_action_logout" msgid="935179188218826050">"Finalizar sessão"</string>
<string name="global_action_screenshot" msgid="8329831278085426283">"Captura de tela"</string>
- <string name="bugreport_title" msgid="5981047024855257269">"Relatório do bug"</string>
+ <string name="bugreport_title" msgid="5981047024855257269">"Relatório de bug"</string>
<string name="bugreport_message" msgid="398447048750350456">"Isto coletará informações sobre o estado atual do dispositivo para enviá-las em uma mensagem de e-mail. Após iniciar o relatório de bugs, será necessário aguardar algum tempo até que esteja pronto para ser enviado."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Relatório interativo"</string>
<string name="bugreport_option_interactive_summary" msgid="229299488536107968">"Use este recurso na maioria das circunstâncias. Ele permite que você acompanhe o progresso do relatório, informe mais detalhes sobre o problema e faça capturas de tela. É possível que ele omita algumas seções menos utilizadas que levam muito tempo na emissão dos relatórios."</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registre seu rosto novamente."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"O rosto não é mais reconhecido. Tente novamente."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Muito parecido, mude de posição."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Olhe mais diretamente para a tela."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Olhe mais diretamente para a tela."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Alinhe sua cabeça na vertical."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Libere espaço entre a cabeça e o smartphone."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Limpe a câmera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Incline a cabeça um pouco menos."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Incline a cabeça um pouco menos."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Incline a cabeça um pouco menos."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Remova tudo que esteja ocultando seu rosto."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpe o sensor na borda superior da tela."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Impossível verificar rosto. Hardware indisponível."</string>
@@ -1241,7 +1241,7 @@
<item quantity="one">Abrir redes Wi-Fi disponíveis</item>
<item quantity="other">Abrir redes Wi-Fi disponíveis</item>
</plurals>
- <string name="wifi_available_title" msgid="3817100557900599505">"Conectar-se a uma rede Wi‑Fi aberta"</string>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Conectar a uma rede Wi‑Fi aberta"</string>
<string name="wifi_available_carrier_network_title" msgid="4527932626916527897">"Conectar à rede Wi‑Fi da operadora"</string>
<string name="wifi_available_title_connecting" msgid="1139126673968899002">"Conectando-se à rede Wi-Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Conectado a uma rede Wi‑Fi"</string>
@@ -1546,7 +1546,7 @@
<string name="storage_usb_drive_label" msgid="4501418548927759953">"Drive USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"Editar"</string>
- <string name="data_usage_warning_title" msgid="6499834033204801605">"Aviso de dados"</string>
+ <string name="data_usage_warning_title" msgid="6499834033204801605">"Alerta de uso de dados"</string>
<string name="data_usage_warning_body" msgid="7340198905103751676">"Você usou <xliff:g id="APP">%s</xliff:g> de dados"</string>
<string name="data_usage_mobile_limit_title" msgid="6561099244084267376">"Limite de dados móveis atingido"</string>
<string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Limite de dados Wi-Fi atingido"</string>
@@ -2027,4 +2027,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> arquivos</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Compartilhamento direto indisponível"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lista de apps"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 2225767..1872869 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Volte a inscrever o rosto."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Impossível reconhecer o rosto. Tente novamente."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Muito parecida, mude de pose."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Olhe mais diretamente para o ecrã."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Olhe mais diretamente para o ecrã."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Endireite a cabeça na vertical."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Desimpeça o espaço entre a cabeça e o telemóvel."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Limpe a câmara."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Rode a cabeça um pouco menos."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Rode a cabeça um pouco menos."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Rode a cabeça um pouco menos."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Remova tudo o que esteja a ocultar o seu rosto."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpe o sensor na extremidade superior do ecrã."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Não pode validar o rosto. Hardware não disponível."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ficheiro</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"A partilha direta não está disponível."</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lista de aplicações"</string>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index b572591..87c9e16 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -228,7 +228,7 @@
<string name="global_action_bug_report" msgid="7934010578922304799">"Relatório de bugs"</string>
<string name="global_action_logout" msgid="935179188218826050">"Finalizar sessão"</string>
<string name="global_action_screenshot" msgid="8329831278085426283">"Captura de tela"</string>
- <string name="bugreport_title" msgid="5981047024855257269">"Relatório do bug"</string>
+ <string name="bugreport_title" msgid="5981047024855257269">"Relatório de bug"</string>
<string name="bugreport_message" msgid="398447048750350456">"Isto coletará informações sobre o estado atual do dispositivo para enviá-las em uma mensagem de e-mail. Após iniciar o relatório de bugs, será necessário aguardar algum tempo até que esteja pronto para ser enviado."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Relatório interativo"</string>
<string name="bugreport_option_interactive_summary" msgid="229299488536107968">"Use este recurso na maioria das circunstâncias. Ele permite que você acompanhe o progresso do relatório, informe mais detalhes sobre o problema e faça capturas de tela. É possível que ele omita algumas seções menos utilizadas que levam muito tempo na emissão dos relatórios."</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registre seu rosto novamente."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"O rosto não é mais reconhecido. Tente novamente."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Muito parecido, mude de posição."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Olhe mais diretamente para a tela."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Olhe mais diretamente para a tela."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Alinhe sua cabeça na vertical."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Libere espaço entre a cabeça e o smartphone."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Limpe a câmera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Incline a cabeça um pouco menos."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Incline a cabeça um pouco menos."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Incline a cabeça um pouco menos."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Remova tudo que esteja ocultando seu rosto."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpe o sensor na borda superior da tela."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Impossível verificar rosto. Hardware indisponível."</string>
@@ -1241,7 +1241,7 @@
<item quantity="one">Abrir redes Wi-Fi disponíveis</item>
<item quantity="other">Abrir redes Wi-Fi disponíveis</item>
</plurals>
- <string name="wifi_available_title" msgid="3817100557900599505">"Conectar-se a uma rede Wi‑Fi aberta"</string>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Conectar a uma rede Wi‑Fi aberta"</string>
<string name="wifi_available_carrier_network_title" msgid="4527932626916527897">"Conectar à rede Wi‑Fi da operadora"</string>
<string name="wifi_available_title_connecting" msgid="1139126673968899002">"Conectando-se à rede Wi-Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Conectado a uma rede Wi‑Fi"</string>
@@ -1546,7 +1546,7 @@
<string name="storage_usb_drive_label" msgid="4501418548927759953">"Drive USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"Editar"</string>
- <string name="data_usage_warning_title" msgid="6499834033204801605">"Aviso de dados"</string>
+ <string name="data_usage_warning_title" msgid="6499834033204801605">"Alerta de uso de dados"</string>
<string name="data_usage_warning_body" msgid="7340198905103751676">"Você usou <xliff:g id="APP">%s</xliff:g> de dados"</string>
<string name="data_usage_mobile_limit_title" msgid="6561099244084267376">"Limite de dados móveis atingido"</string>
<string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Limite de dados Wi-Fi atingido"</string>
@@ -2027,4 +2027,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> arquivos</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Compartilhamento direto indisponível"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lista de apps"</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index ad7e672..69c2fe8 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -574,11 +574,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Reînregistrați-vă chipul."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Nu se mai poate recunoaște fața. Încercați din nou."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Prea asemănător, schimbați poziția."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Priviți mai direct spre ecran."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Priviți mai direct spre ecran."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Îndreptați capul pe verticală."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Eliberați spațiul dintre cap și telefon."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Curățați camera foto."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Întoarceți capul mai puțin."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Întoarceți capul mai puțin."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Întoarceți capul mai puțin."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Eliminați orice vă ascunde chipul."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Curățați senzorul de la marginea de sus a ecranului."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nu se poate confirma fața. Hardware-ul nu este disponibil."</string>
@@ -2063,4 +2063,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> fișier</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Trimiterea directă nu este disponibilă"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lista de aplicații"</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 7c63a6b..f45b9fb 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -232,7 +232,7 @@
<string name="global_action_bug_report" msgid="7934010578922304799">"Отчет об ошибке"</string>
<string name="global_action_logout" msgid="935179188218826050">"Закончить сеанс"</string>
<string name="global_action_screenshot" msgid="8329831278085426283">"Скриншот"</string>
- <string name="bugreport_title" msgid="5981047024855257269">"Сообщение об ошибке"</string>
+ <string name="bugreport_title" msgid="5981047024855257269">"Отчет об ошибке"</string>
<string name="bugreport_message" msgid="398447048750350456">"Информация о текущем состоянии вашего устройства будет собрана и отправлена по электронной почте. Подготовка отчета займет некоторое время."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактивный отчет"</string>
<string name="bugreport_option_interactive_summary" msgid="229299488536107968">"Рекомендуем этот вариант в большинстве случаев, чтобы отслеживать статус отчета, указывать дополнительные данные о проблеме и делать скриншоты. Некоторые разделы могут быть исключены, чтобы сократить время подготовки отчета."</string>
@@ -577,11 +577,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Повторите попытку."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Не удалось распознать лицо. Повторите попытку."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Слишком похожее выражение лица. Измените позу."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Смотрите прямо в экран."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Смотрите прямо в экран."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Выровняйте голову по вертикали."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Лицо не должно быть ничем закрыто."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Протрите камеру."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Держите голову ровнее."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Держите голову ровнее."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Держите голову ровнее."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Ваше лицо плохо видно."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Очистите сканер в верхней части экрана."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Не удалось распознать лицо. Сканер недоступен."</string>
@@ -2099,4 +2099,5 @@
<item quantity="other">\"<xliff:g id="FILE_NAME_2">%s</xliff:g>\" и ещё <xliff:g id="COUNT_3">%d</xliff:g> файла</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Функция Direct Share недоступна."</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Список приложений"</string>
</resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 2991f63..29a2dd23 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"ඔබේ මුහුණ යළි ලියාපදිංචි කරන්න."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"තවදුරටත් මුහුණ හඳුනාගත නොහැක. නැවත උත්සාහ කරන්න."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"ඉතා සමානයි, ඔබේ හැඩ ගැසීම වෙනස් කරන්න."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"තිරය වෙත තවත් ඍජුව බලන්න."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"තිරය වෙත තවත් ඍජුව බලන්න."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"ඔබේ හිස සිරස් ආකාරයේ කෙළින් කරන්න."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"ඔබේ හිස සහ දුරකථනය අතර ඉඩ ඉවත් කරන්න."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"කැමරාව පිරිසිදු කරන්න."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"ඔබේ හිස ටිකක් අඩුවෙන් කරකවන්න."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ඔබේ හිස ටිකක් අඩුවෙන් කරකවන්න."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ඔබේ හිස ටිකක් අඩුවෙන් කරකවන්න."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"ඔබේ මුහුණ සඟවන කිසිවක් ඉවත් කරන්න."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"තිරයේ ඉහළ කෙළවරේ සංවේදකය පිරිසිදු කරන්න."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"මුහුණ සත්යාපනය කළ නොහැක. දෘඩාංගය නොමැත."</string>
@@ -2029,4 +2029,5 @@
<item quantity="other">ගොනු<xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g></item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"ඍජු බෙදා ගැනීම නොලැබේ"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"යෙදුම් ලැයිස්තුව"</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 630b799..33dc6f4 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -78,7 +78,7 @@
<string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"V predvolenom nastavení nie je identifikácia volajúceho obmedzená. Ďalší hovor: Obmedzené"</string>
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"V predvolenom nastavení nie je identifikácia volajúceho obmedzená. Ďalší hovor: Bez obmedzenia"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Služba nie je poskytovaná."</string>
- <string name="CLIRPermanent" msgid="3377371145926835671">"Nemôžete meniť nastavenia identifikácie volajúceho."</string>
+ <string name="CLIRPermanent" msgid="3377371145926835671">"Nemôžete meniť nastavenie identifikácie volajúcich."</string>
<string name="RestrictedOnDataTitle" msgid="5221736429761078014">"Žiadna mobilná dátová služba"</string>
<string name="RestrictedOnEmergencyTitle" msgid="6855466023161191166">"Tiesňové volania nie sú k dispozícii"</string>
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Žiadne hlasové hovory"</string>
@@ -308,9 +308,9 @@
<string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparát"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"fotenie a natáčanie videí"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"Povoliť aplikácii <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> snímať fotky a zaznamenávať video?"</string>
- <string name="permgrouplab_calllog" msgid="8798646184930388160">"Denníky hovorov"</string>
- <string name="permgroupdesc_calllog" msgid="3006237336748283775">"čítanie a zapisovanie do denníka hovorov telefónu"</string>
- <string name="permgrouprequest_calllog" msgid="8487355309583773267">"Povoliť aplikácii <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> prístup k denníku hovorov telefónu?"</string>
+ <string name="permgrouplab_calllog" msgid="8798646184930388160">"Zoznam hovorov"</string>
+ <string name="permgroupdesc_calllog" msgid="3006237336748283775">"čítať a zapisovať do zoznamu hovorov"</string>
+ <string name="permgrouprequest_calllog" msgid="8487355309583773267">"Povoliť aplikácii <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> prístup k zoznamu hovorov?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Telefón"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"telefonovanie a správu hovorov"</string>
<string name="permgrouprequest_phone" msgid="9166979577750581037">"Povoliť aplikácii <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> uskutočňovať a spravovať telefonické hovory?"</string>
@@ -406,7 +406,7 @@
<string name="permlab_writeCallLog" msgid="8552045664743499354">"zapisovať do denníka hovorov"</string>
<string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Umožňuje aplikácii upravovať denník hovorov vo vašom tablete vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Škodlivé aplikácie to môžu zneužiť na vymazanie alebo úpravu vášho denníka hovorov."</string>
<string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Umožňuje aplikácii upravovať denník hovorov vo vašom televízore vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Škodlivé aplikácie to môžu zneužiť na vymazanie alebo úpravu vášho denníka hovorov."</string>
- <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Umožňuje aplikácii upravovať denník hovorov vo vašom telefóne vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Škodlivé aplikácie to môžu zneužiť na vymazanie alebo úpravu vášho denníka hovorov."</string>
+ <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Umožňuje aplikácii upravovať zoznam hovorov vo vašom telefóne vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Škodlivé aplikácie to môžu zneužiť na vymazanie alebo úpravu vášho zoznamu hovorov."</string>
<string name="permlab_bodySensors" msgid="4683341291818520277">"prístup k telesným senzorom (ako sú snímače tepu)"</string>
<string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Umožňuje aplikácii získať prístup k údajom senzorov monitorujúcich vašu fyzickú kondíciu (napríklad pulz)."</string>
<string name="permlab_readCalendar" msgid="6716116972752441641">"Čítanie udalostí kalendára a podrobností"</string>
@@ -577,11 +577,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Znova zaregistrujte svoju tvár."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Tvár už nie je možné rozpoznať. Skúste to znova."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Príliš rovnaké, zmeňte postoj."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Pozrite sa priamejšie na obrazovku."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Pozrite sa priamejšie na obrazovku."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Zvisle vyrovnajte hlavu."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Odstráňte prekážky medzi vašou hlavou a telefónom."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Vyčistite fotoaparát."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Otočte hlavu o niečo menej."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Otočte hlavu o niečo menej."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Otočte hlavu o niečo menej."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Odstráňte všetko, čo vám zakrýva tvár."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Vyčistite senzor v hornom okraji obrazovky."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Tvár sa nedá overiť. Hardvér nie je k dispozícii."</string>
@@ -2099,4 +2099,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> súbor</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Priame zdieľanie nie je k dispozícii"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Zoznam aplikácií"</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index a20edcb..7bd13fc 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -231,7 +231,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Klic v sili"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Poročilo o napakah"</string>
<string name="global_action_logout" msgid="935179188218826050">"Končaj sejo"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"Posnetek zaslona"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Posnetek"</string>
<string name="bugreport_title" msgid="5981047024855257269">"Poročilo o napakah"</string>
<string name="bugreport_message" msgid="398447048750350456">"S tem bodo zbrani podatki o trenutnem stanju naprave, ki bodo poslani v e-poštnem sporočilu. Izvedba poročila o napakah in priprava trajata nekaj časa, zato bodite potrpežljivi."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktivno poročilo"</string>
@@ -577,11 +577,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Znova prijavite svoj obraz."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Obraza ni več mogoče prepoznati. Poskusite znova."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Preveč podobno, spremenite položaj."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Glejte bolj naravnost v zaslon."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Glejte bolj naravnost v zaslon."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Zravnajte glavo."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Povečajte razmik med glavo in telefonom."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Očistite fotoaparat."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Glejte malce bolj naravnost."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Malce manj nagnite glavo."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Glejte malce bolj naravnost."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Umaknite vse, kar vam morda zakriva obraz."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Očistite tipalo na zgornjem robu zaslona."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Obraza ni mogoče preveriti. Str. opr. ni na voljo."</string>
@@ -2099,4 +2099,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> in še <xliff:g id="COUNT_3">%d</xliff:g> datotek</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Neposredna skupna raba ni na voljo"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Seznam aplikacij"</string>
</resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 37bff1a..5c7b014 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -304,7 +304,7 @@
<string name="permgrouprequest_camera" msgid="1299833592069671756">"Të lejohet që <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> të nxjerrë fotografi dhe të regjistrojë video?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Evidencat e telefonatave"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"lexo dhe shkruaj evidencën e telefonatave"</string>
- <string name="permgrouprequest_calllog" msgid="8487355309583773267">"Të <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> të ketë qasje në evidencat e tua të telefonatave?"</string>
+ <string name="permgrouprequest_calllog" msgid="8487355309583773267">"Të lejohet <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> të ketë qasje në evidencat e tua të telefonatave?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Telefoni"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"kryej dhe menaxho telefonata"</string>
<string name="permgrouprequest_phone" msgid="9166979577750581037">"Të lejohet që <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> të kryejë dhe të menaxhojë telefonata?"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Regjistroje përsëri fytyrën tënde."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Fytyra nuk mund të njihet më. Provo përsëri."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Tepër e ngjashme, ndrysho pozën"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Shiko më drejt tek ekrani."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Shiko më drejt tek ekrani."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Drejtoje kokën vertikalisht"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Pastroje hapësirën mes kokës sate dhe telefonit."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Pastro kamerën."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Ktheje kokën pak më pak."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Ktheje kokën pak më pak."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Ktheje kokën pak më pak."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Hiq gjithçka që fsheh fytyrën tënde."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Pastro sensorin në anën e sipërme të ekranit."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Fytyra s\'mund të verifikohet. Hardueri nuk ofrohet."</string>
@@ -2028,4 +2028,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> skedar</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Ndarja e drejtpërdrejtë nuk ofrohet"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Lista e aplikacioneve"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index a32f279..52bfbe2 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -574,11 +574,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Поново региструјте лице."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Више не може да се препозна лице. Пробајте поново."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Превише је слично, промените позу."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Гледајте право у екран."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Гледајте право у екран."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Исправите главу."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Ослободите простор између главе и телефона."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Очистите камеру."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Мало мање померите главу."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Мало мање померите главу."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Мало мање померите главу."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Уклоните све што вам заклања лице."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Очистите сензор на горњој ивици екрана."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Провера лица није успела. Хардвер није доступан."</string>
@@ -899,7 +899,7 @@
<string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
<string name="granularity_label_character" msgid="7336470535385009523">"знак"</string>
<string name="granularity_label_word" msgid="7075570328374918660">"реч"</string>
- <string name="granularity_label_link" msgid="5815508880782488267">"веза"</string>
+ <string name="granularity_label_link" msgid="5815508880782488267">"линк"</string>
<string name="granularity_label_line" msgid="5764267235026120888">"ред"</string>
<string name="factorytest_failed" msgid="5410270329114212041">"Фабричко тестирање није успело"</string>
<string name="factorytest_not_system" msgid="4435201656767276723">"Радња FACTORY_TEST је подржана само за пакете инсталиране у директоријуму /system/app."</string>
@@ -2063,4 +2063,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> и још <xliff:g id="COUNT_3">%d</xliff:g> датотека</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Директно дељење није доступно"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Листа апликација"</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index d281261..52c532d 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -296,7 +296,7 @@
<string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"spela in ljud"</string>
<string name="permgrouprequest_microphone" msgid="9167492350681916038">"Vill du ge <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> behörighet att spela in ljud?"</string>
- <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Fysisk aktivitet"</string>
+ <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Fysiska aktivitet"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"åtkomst till data om fysisk aktivitet"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"Vill du ge <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to åtkomst till data om fysisk aktivitet?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registrera ansiktet på nytt."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Ansiktet kan inte längre kännas igen. Försök igen."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"För likt. Ändra ansiktsposition."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Titta rakt på skärmen."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Titta rakt på skärmen."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Räta på huvudet vertikalt."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Se till att ditt ansikte inte skyms för mobilen."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Rengör kameran."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Vrid mindre på huvudet."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Vrid mindre på huvudet."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Vrid mindre på huvudet."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Ta bort allt som täcker ansiktet."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Rengör sensorn på skärmens överkant."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Ansiktsverifiering går ej. Otillgänglig maskinvara."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> fil</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Dela direkt är inte tillgängligt"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Applista"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index f036296..1fa17dc 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -304,7 +304,7 @@
<string name="permgrouprequest_camera" msgid="1299833592069671756">"Ungependa kuruhusu <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> kupiga picha na kurekodi video?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Rekodi ya nambari za simu"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"kusoma na kuandika rekodi ya nambari za simu"</string>
- <string name="permgrouprequest_calllog" msgid="8487355309583773267">"Ungependa kuruhusu <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ifikie rekodi zako za nambari za simu?"</string>
+ <string name="permgrouprequest_calllog" msgid="8487355309583773267">"Ungependa kuiruhusu <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ifikie rekodi zako za nambari za simu?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Simu"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"piga na udhibiti simu"</string>
<string name="permgrouprequest_phone" msgid="9166979577750581037">"Ungependa kuiruhusu <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ipige na kudhibiti simu?"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Tafadhali sajili uso wako tena."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Haiwezi tena kutambua uso. Jaribu tena."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Inafanana sana, tafadhali badilisha mkao wako."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Tafadhali angalia skrini moja kwa moja."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Tafadhali angalia skrini moja kwa moja."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Tafadhali simamisha kichwa chako wima."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Safisha nafasi iliyo kati ya kichwa chako na simu."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Tafadhali safisha kamera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Geuza kichwa chako kidogo."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Geuza kichwa chako kidogo."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Geuza kichwa chako kidogo."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Ondoa kitu chochote kinachoficha uso wako."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Safisha kitambuzi kwenye ukingo wa juu wa skrini."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Imeshindwa kuthibitisha uso. Maunzi hayapatikani."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one">Faili <xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g></item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Huwezi kushiriki moja kwa moja"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Orodha ya programu"</string>
</resources>
diff --git a/core/res/res/values-ta-watch/strings.xml b/core/res/res/values-ta-watch/strings.xml
index 737f6d0..3277e69 100644
--- a/core/res/res/values-ta-watch/strings.xml
+++ b/core/res/res/values-ta-watch/strings.xml
@@ -20,6 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="android_upgrading_apk" msgid="1090732262010398759">"பயன்பாடு: <xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <string name="android_upgrading_apk" msgid="1090732262010398759">"ஆப்ஸ்: <xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="permgrouplab_sensors" msgid="202675452368612754">"உணர்விகள்"</string>
</resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 40e2816..9d9f280 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -466,9 +466,9 @@
<string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"டிவியின் நேர மண்டலத்தை மாற்ற, ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"மொபைலின் நேர மண்டலத்தை மாற்ற, ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permlab_getAccounts" msgid="1086795467760122114">"சாதனத்தில் கணக்குகளைக் கண்டறிதல்"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"டேப்லெட் மூலம் அறியப்பட்ட கணக்குகளின் பட்டியலைப் பெற ஆப்ஸை அனுமதிக்கிறது. நீங்கள் நிறுவிய பயன்பாடுகள் மூலம் உருவாக்கப்பட்ட எல்லா கணக்குகளும் இதில் உள்ளடங்கலாம்."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"டேப்லெட் மூலம் அறியப்பட்ட கணக்குகளின் பட்டியலைப் பெற ஆப்ஸை அனுமதிக்கிறது. நீங்கள் நிறுவிய ஆப்ஸ் மூலம் உருவாக்கப்பட்ட எல்லா கணக்குகளும் இதில் உள்ளடங்கலாம்."</string>
<string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"டிவி அறிந்த கணக்குகளின் பட்டியலைப் பெற, ஆப்ஸை அனுமதிக்கிறது. இதில் நிறுவிய பயன்பாடுகளினால் உருவாக்கப்பட்ட எல்லா கணக்குகளும் அடங்கலாம்."</string>
- <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"மொபைல் மூலம் அறியப்பட்ட கணக்குகளின் பட்டியலைப் பெற ஆப்ஸை அனுமதிக்கிறது. நீங்கள் நிறுவிய பயன்பாடுகள் மூலம் உருவாக்கப்பட்ட எல்லா கணக்குகளும் இதில் உள்ளடங்கலாம்."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"மொபைல் மூலம் அறியப்பட்ட கணக்குகளின் பட்டியலைப் பெற ஆப்ஸை அனுமதிக்கிறது. நீங்கள் நிறுவிய ஆப்ஸ் மூலம் உருவாக்கப்பட்ட எல்லா கணக்குகளும் இதில் உள்ளடங்கலாம்."</string>
<string name="permlab_accessNetworkState" msgid="4951027964348974773">"நெட்வொர்க் இணைப்புகளைக் காட்டு"</string>
<string name="permdesc_accessNetworkState" msgid="8318964424675960975">"தற்போது இருக்கும் நெட்வொர்க்குகள் எவை மற்றும் இணைக்கப்பட்டுள்ளவை எவை போன்ற நெட்வொர்க் இணைப்புகள் குறித்த தகவலைப் பார்க்கப் ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permlab_createNetworkSockets" msgid="7934516631384168107">"முழுமையான நெட்வொர்க் அணுகலைக் கொண்டிருக்கும்"</string>
@@ -553,12 +553,9 @@
<string name="permdesc_manageFace" msgid="8919637120670185330">"உபயோகிப்பதற்காக முக டெம்ப்ளேட்டுகளை சேர்க்கும்/நீக்கும் முறைகளை இயக்க, ஆப்ஸை அனுமதிக்கும்."</string>
<string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"முக அங்கீகாரத்திற்கான வன்பொருளைப் பயன்படுத்துதல்"</string>
<string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"அடையாளம் காண்பதற்கு, முக அங்கீகார வன்பொருளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கிறது"</string>
- <!-- no translation found for face_recalibrate_notification_name (3976629945250435054) -->
- <skip />
- <!-- no translation found for face_recalibrate_notification_title (4087620069451499365) -->
- <skip />
- <!-- no translation found for face_recalibrate_notification_content (5530308842361499835) -->
- <skip />
+ <string name="face_recalibrate_notification_name" msgid="3976629945250435054">"முக அங்கீகாரம்"</string>
+ <string name="face_recalibrate_notification_title" msgid="4087620069451499365">"முகத்தை மீண்டும் பதிவுசெய்யவும்"</string>
+ <string name="face_recalibrate_notification_content" msgid="5530308842361499835">"அடையாளத்தை மேம்படுத்த முகத்தை மீண்டும் பதிவுசெய்யவும்"</string>
<string name="face_acquired_insufficient" msgid="2767330364802375742">"முகம் தெளிவாகப் பதிவாகவில்லை. மீண்டும் முயலவும்."</string>
<string name="face_acquired_too_bright" msgid="5005650874582450967">"அதிக ஒளிர்வு. மிதமான ஒளியில் முயலவும்."</string>
<string name="face_acquired_too_dark" msgid="1966194696381394616">"இருட்டாக உள்ளது. பிரகாசமான ஒளியில் முயலவும்."</string>
@@ -574,11 +571,16 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"உங்கள் முகத்தை மீண்டும் பதிவுசெய்யுங்கள்."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"முகத்தைக் கண்டறிய இயலவில்லை. மீண்டும் முயலவும்."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"மீண்டும் அதே போஸ் தருகிறீர்கள், வேறு முயலுங்கள்."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"திரையில் முழுமுகம் தெரியுமாறு நேராகப் பார்க்கவும்."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"திரையில் முழுமுகம் தெரியுமாறு நேராகப் பார்க்கவும்."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"உங்கள் தலையை நேராக வைக்கவும்."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"முகத்திற்கும் மொபைலுக்குமான இடைவெளியை குறைக்கவும்."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"கேமராவைத் துடைக்கவும்"</string>
+ <!-- no translation found for face_acquired_pan_too_extreme (4581629343077288178) -->
+ <skip />
+ <!-- no translation found for face_acquired_tilt_too_extreme (4019954263012496468) -->
+ <skip />
+ <!-- no translation found for face_acquired_roll_too_extreme (6312973147689664409) -->
+ <skip />
+ <!-- no translation found for face_acquired_obscured (5357207702967893283) -->
+ <skip />
+ <!-- no translation found for face_acquired_sensor_dirty (2535761002815565222) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"முகத்தைச் சரிபார்க்க இயலவில்லை. வன்பொருள் இல்லை."</string>
@@ -1909,7 +1911,7 @@
<string name="profile_encrypted_message" msgid="6964994232310195874">"பணிக் கணக்கை திறக்க, தட்டுக"</string>
<string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> உடன் இணைக்கப்பட்டது"</string>
<string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"கோப்புகளைப் பார்க்க, தட்டவும்"</string>
- <string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
+ <string name="app_info" msgid="6856026610594615344">"ஆப்ஸ் தகவல்"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="5268556852031489931">"டெமோவைத் தொடங்குகிறது…"</string>
<string name="demo_restarting_message" msgid="952118052531642451">"சாதனத்தை மீட்டமைக்கிறது…"</string>
@@ -2031,4 +2033,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ஃபைல்</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"நேரடிப் பகிர்வு இல்லை"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"ஆப்ஸ் பட்டியல்"</string>
</resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 87dfa95..cc6583f 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -571,11 +571,14 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"దయచేసి మీ ముఖాన్ని మళ్లీ నమోదు చేయండి."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"ఇక ముఖం గుర్తించలేదు. మళ్లీ ప్రయత్నించండి."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"ఒకే మాదిరిగా ఉంది, దయచేసి భంగిమను మార్చండి."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"దయచేసి స్క్రీన్ వైపు మరింత సూటిగా చూడండి."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"దయచేసి స్క్రీన్ వైపు మరింత సూటిగా చూడండి."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"దయచేసి మీ తలను నిలువుగా, నిటారుగా ఉంచండి."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"మీ తలకు, ఫోన్కు మధ్యన ఏదీ లేదని నిర్దారించుకోండి."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"దయచేసి కెమెరాను శుభ్రం చేయండి."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"మీ తలను ఇంకాస్త తక్కువ తిప్పండి."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"మీ తలను ఇంకాస్త తక్కువ తిప్పండి."</string>
+ <!-- no translation found for face_acquired_roll_too_extreme (6312973147689664409) -->
+ <skip />
+ <!-- no translation found for face_acquired_obscured (5357207702967893283) -->
+ <skip />
+ <!-- no translation found for face_acquired_sensor_dirty (2535761002815565222) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ముఖం ధృవీకరించలేరు. హార్డ్వేర్ అందుబాటులో లేదు."</string>
@@ -2028,4 +2031,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ఫైల్</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"డైరెక్ట్ షేర్ అందుబాటులో లేదు"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"యాప్ల జాబితా"</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 86a08d4..226c5fe 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -241,7 +241,7 @@
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"โหมดปิดเสียง"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"ปิดเสียงไว้"</string>
<string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"เปิดเสียงแล้ว"</string>
- <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"โหมดใช้งานบนเครื่องบิน"</string>
+ <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"โหมดบนเครื่องบิน"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"เปิดโหมดใช้งานบนเครื่องบิน"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"โหมดใช้งานบนเครื่องบินปิดทำงานอยู่"</string>
<string name="global_action_settings" msgid="1756531602592545966">"การตั้งค่า"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"โปรดลงทะเบียนใบหน้าอีกครั้ง"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"จำใบหน้าไม่ได้แล้ว ลองอีกครั้ง"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"ใกล้เคียงเกินไป โปรดเปลี่ยนท่าโพส"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"โปรดมองตรงไปที่หน้าจอ"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"โปรดมองตรงไปที่หน้าจอ"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"โปรดตั้งศีรษะให้ตรง"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"ดูว่าไม่มีสิ่งใดขวางระหว่างใบหน้าและโทรศัพท์"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"โปรดทำความสะอาดกล้อง"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"จัดตำแหน่งศีรษะให้ตรง"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"จัดตำแหน่งศีรษะให้ตรง"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"จัดตำแหน่งศีรษะให้ตรง"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"เอาสิ่งที่ปิดบังใบหน้าออก"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"ทำความสะอาดเซ็นเซอร์ที่ขอบด้านบนของหน้าจอ"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ยืนยันใบหน้าไม่ได้ ฮาร์ดแวร์ไม่พร้อมใช้งาน"</string>
@@ -1595,7 +1595,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"การแสดงผลแบบไร้สาย"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"แคสต์"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"เชื่อมต่อกับอุปกรณ์"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ส่งหน้าจอไปยังอุปกรณ์"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"แคสต์หน้าจอไปยังอุปกรณ์"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"กำลังค้นหาอุปกรณ์…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"การตั้งค่า"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"ยกเลิกการเชื่อมต่อ"</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> และอีก <xliff:g id="COUNT_1">%d</xliff:g> ไฟล์</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"การแชร์โดยตรงไม่พร้อมใช้งาน"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"รายชื่อแอป"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 3adc3f2..2b0436c 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Paki-enroll muli ang iyong mukha."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Hindi na makilala ang mukha. Subukang muli."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Masyadong magkatulad, pakibago ang pose mo."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Tumingin nang mas direkta sa screen."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Tumingin nang mas direkta sa screen."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Pakituwid ang iyong mukha."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Alisin ang nasa pagitan ng ulo mo at ng telepono."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Pakilinis ang camera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Huwag masyadong lumingon."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Huwag masyadong tumingala o yumuko."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Huwag masyadong lumingon."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Alisin ang anumang humaharang sa iyong mukha."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Linisinin ang sensor sa itaas na gilid ng screen."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Di ma-verify ang mukha. Di available ang hardware."</string>
@@ -2027,4 +2027,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> na file</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Hindi available ang direktang pagbabahagi"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Listahan ng mga app"</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 9d99bc75..847680e 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Lütfen yüzünüzü yeniden kaydedin."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Yüz artık tanınamıyor. Tekrar deneyin."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Duruşunuz çok benzer, lütfen pozunuzu değiştirin."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Lütfen ekrana daha doğrudan bakın."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Lütfen ekrana daha doğrudan bakın."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Lütfen başınızı tam dik olacak şekilde tutun."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Başınız ve telefon arasındaki engelleri ortadan kaldırın."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Lütfen kamerayı temizleyin."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Başınızı biraz daha az çevirin."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Başınızı biraz daha az çevirin."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Başınızı biraz daha az çevirin."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Yüzünüzün görünmesini engelleyen şeyleri kaldırın."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Ekranın üst kenarındaki sensörü temizleyin."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Yüz doğrulanamıyor. Donanım kullanılamıyor."</string>
@@ -1813,12 +1813,12 @@
<item quantity="one">1 dakika için (şu saate kadar: <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="736789408293052283">
- <item quantity="other">%1$d saat için (şu saate kadar: <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
- <item quantity="one">1 saat için (şu saate kadar: <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d saat (şu saate kadar: <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">1 saat (şu saate kadar: <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="4787552595253082371">
- <item quantity="other">%1$d saat için (şu saate kadar: <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
- <item quantity="one">1 saat için (şu saate kadar: <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d saat (şu saate kadar: <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">1 saat (şu saate kadar: <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
<item quantity="other">%d dakika süreyle</item>
@@ -1829,12 +1829,12 @@
<item quantity="one">1 dakika için</item>
</plurals>
<plurals name="zen_mode_duration_hours" formatted="false" msgid="6571961796799076730">
- <item quantity="other">%d saat için</item>
- <item quantity="one">1 saat için</item>
+ <item quantity="other">%d saat</item>
+ <item quantity="one">1 saat</item>
</plurals>
<plurals name="zen_mode_duration_hours_short" formatted="false" msgid="6748277774662434217">
- <item quantity="other">%d saat için</item>
- <item quantity="one">1 saat için</item>
+ <item quantity="other">%d saat</item>
+ <item quantity="one">1 saat</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Şu saate kadar: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (sonraki alarma) saatine kadar"</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> dosya</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Doğrudan paylaşım mevcut değil"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Uygulama listesi"</string>
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index e99e9e5..d3eaff6 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -296,7 +296,7 @@
<string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
<string name="permgroupdesc_sms" msgid="4656988620100940350">"надсилати та переглядати SMS-повідомлення"</string>
<string name="permgrouprequest_sms" msgid="7168124215838204719">"Дозволити додатку <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> надсилати та переглядати SMS?"</string>
- <string name="permgrouplab_storage" msgid="1971118770546336966">"Зберігання"</string>
+ <string name="permgrouplab_storage" msgid="1971118770546336966">"Пам’ять"</string>
<string name="permgroupdesc_storage" msgid="637758554581589203">"отримувати доступ до фотографій, мультимедійного вмісту та файлів на вашому пристрої"</string>
<string name="permgrouprequest_storage" msgid="7885942926944299560">"Надати додатку <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> доступ до фото, медіа та файлів на пристрої?"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"Мікрофон"</string>
@@ -577,11 +577,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Повторно проскануйте обличчя."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Розпізнати обличчя вже не вдається. Повторіть спробу."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Надто схоже на попередню спробу, змініть позу."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Дивіться просто на екран."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Дивіться просто на екран."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Тримайте голову вертикально."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Щось затуляє ваше обличчя."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Протріть камеру."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Трохи перемістіть обличчя."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Трохи перемістіть обличчя."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Трохи поверніть обличчя."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Приберіть об’єкти, які затуляють ваше обличчя."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Очистьте датчик угорі екрана."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Не вдається перевірити обличчя. Апаратне забезпечення недоступне."</string>
@@ -2099,4 +2099,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> і ще <xliff:g id="COUNT_3">%d</xliff:g> файлу</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Прямий обмін даними недоступний"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Список додатків"</string>
</resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index fc0ae97..ebf715a 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -291,7 +291,7 @@
<string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS پیغامات بھیجیں اور دیکھیں"</string>
<string name="permgrouprequest_sms" msgid="7168124215838204719">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> کو SMS پیغامات بھیجنے اور انہیں ملاحظہ کرنے کی اجازت دیں؟"</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"اسٹوریج"</string>
- <string name="permgroupdesc_storage" msgid="637758554581589203">"اپنے آلہ پر تصاویر، میڈیا اور فائلوں تک رسائی حاصل کریں"</string>
+ <string name="permgroupdesc_storage" msgid="637758554581589203">"آپ کے آلہ پر تصاویر، میڈیا اور فائلوں تک رسائی حاصل کر سکتی ہیں"</string>
<string name="permgrouprequest_storage" msgid="7885942926944299560">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> کو آپ کے آلہ پر تصاویر، میڈیا اور فائلوں تک رسائی کی اجازت دیں؟"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"مائکروفون"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"آڈیو ریکارڈ کریں"</string>
@@ -571,11 +571,14 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"براہ کرم اپنے چہرے کو دوبارہ مندرج کریں۔"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"اب چہرے کی شناخت نہیں کر سکتے۔ پھر آزمائيں۔"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"کافی ملتا جلتا ہے، براہ کرم اپنا پوز بدلیں۔"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"براہ کرم اسکرین کی طرف چہرے کو بالکل سیدھا رکھیں۔"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"براہ کرم اسکرین کی طرف چہرے کو بالکل سیدھا رکھیں۔"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"براہ کرم اپنا سر عمودی طور پر سیدھا کریں۔"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"اپنے سر اور فون کے درمیان جگہ ختم کریں۔"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"براہ کرم کیمرا صاف کریں۔"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"اپنا سر تھوڑا کم کریں۔"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"اپنا سر تھوڑا کم کریں۔"</string>
+ <!-- no translation found for face_acquired_roll_too_extreme (6312973147689664409) -->
+ <skip />
+ <!-- no translation found for face_acquired_obscured (5357207702967893283) -->
+ <skip />
+ <!-- no translation found for face_acquired_sensor_dirty (2535761002815565222) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"چہرے کی توثیق نہیں کی جا سکی۔ ہارڈ ویئر دستیاب نہیں ہے۔"</string>
@@ -2028,4 +2031,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> فائل</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"بلاواسطہ اشتراک دستیاب نہیں ہے"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"ایپس کی فہرست"</string>
</resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 1bacf6e..4105b2a 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -554,8 +554,8 @@
<string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"yuzni aniqlash qurilmasidan foydalanish"</string>
<string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Haqiqiylikni tekshirish uchun skanerdan foydalanish imkonini beradi"</string>
<string name="face_recalibrate_notification_name" msgid="3976629945250435054">"Yuz tekshiruvi"</string>
- <string name="face_recalibrate_notification_title" msgid="4087620069451499365">"Yuzingizni yana roʻyxatdan oʻtkazing"</string>
- <string name="face_recalibrate_notification_content" msgid="5530308842361499835">"Yuzingizni tanishni yaxshilash uchun yuzingizni yana bir marta roʻyxatdan oʻtkazing"</string>
+ <string name="face_recalibrate_notification_title" msgid="4087620069451499365">"Yuzingizni yana qayd qiling"</string>
+ <string name="face_recalibrate_notification_content" msgid="5530308842361499835">"Yuzingiz yanada yaxshiroq aniqlanishi uchun uni yana bir marta qayd qiling"</string>
<string name="face_acquired_insufficient" msgid="2767330364802375742">"Yuz ravshan suratga olinmadi. Qaytadan urining."</string>
<string name="face_acquired_too_bright" msgid="5005650874582450967">"Juda yorqin. Biroz soyaroq joy tanlang."</string>
<string name="face_acquired_too_dark" msgid="1966194696381394616">"Juda qorongʻi. Atrofingizni yoriting."</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Yuzingizni qaytadan qayd qildiring."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Yuz tanilmadi. Qaytadan urining."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Yuz ifodasi oldingiday. Holatingizni oʻzgartiring."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Ekranga tik qarang."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Ekranga tik qarang."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Boshingizni tik tuting."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Boshingiz va telefon orasidagi joyni olib tashlang."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Kamerani tozalang."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Boshingizni asta buring."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Boshingizni asta buring."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Boshingizni asta buring."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Yuzingizni berkitayotgan narsalarni olib tahlang."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Ekranning tepasidagi sensorni tozalang."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Yuzingiz tasdiqlanmadi. Qurilma ishlamayapti."</string>
@@ -1596,8 +1596,8 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"Simsiz monitor"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"Translatsiya qilish"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"Qurilmaga ulanish"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Ekrandagi tasvirni qurilmaga uzatish"</string>
- <string name="media_route_chooser_searching" msgid="4776236202610828706">"Qurilmalar izlanmoqda..."</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Ekran translatsiyasi"</string>
+ <string name="media_route_chooser_searching" msgid="4776236202610828706">"Qurilmalar qidirilmoqda..."</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Sozlamalar"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Uzish"</string>
<string name="media_route_status_scanning" msgid="7279908761758293783">"Qidirilmoqda..."</string>
@@ -2028,4 +2028,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ta fayl</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Bevosita ulashuv ishlamaydi"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Ilovalar roʻyxati"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 6b13234..4aa0722 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Vui lòng đăng ký lại khuôn mặt của bạn."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Không nhận ra khuôn mặt. Hãy thử lại."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Khuôn mặt quá giống nhau, vui lòng đổi tư thế."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Vui lòng nhìn thẳng vào màn hình."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Vui lòng nhìn thẳng vào màn hình."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Vui lòng giữ thẳng đầu."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Loại bỏ vật chắn giữa đầu và điện thoại."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Vui lòng lau sạch máy ảnh."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Hãy bớt di chuyển đầu."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Hãy bớt di chuyển đầu."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Hãy bớt di chuyển đầu."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Hãy loại bỏ mọi thứ che khuất khuôn mặt bạn."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Hãy lau sạch cảm biến ở cạnh trên của màn hình."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Không thể xác minh khuôn mặt. Phần cứng không có sẵn."</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> tệp</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Không thể chia sẻ trực tiếp"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Danh sách ứng dụng"</string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 8dfbea9..39ad8e2 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"请重新注册您的面孔。"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"已无法识别人脸,请重试。"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"与先前的姿势太相近,请换一个姿势。"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"请直视屏幕。"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"请直视屏幕。"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"请将头摆正。"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"请清除头部和手机之间的障碍物。"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"请将摄像头擦拭干净。"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"请将您的头稍微上下倾斜。"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"请将您的头稍微上下倾斜。"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"请将您的头稍微左右旋转。"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"请移除所有遮挡您面部的物体。"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"请将屏幕顶部边缘的传感器擦拭干净。"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"无法验证人脸。硬件无法使用。"</string>
@@ -1364,7 +1364,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"分享"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"拒绝"</string>
<string name="select_input_method" msgid="4653387336791222978">"选择输入法"</string>
- <string name="show_ime" msgid="2506087537466597099">"开启后,连接到实体键盘时,它会一直显示在屏幕上"</string>
+ <string name="show_ime" msgid="2506087537466597099">"在连接到实体键盘时保持显示"</string>
<string name="hardware" msgid="194658061510127999">"显示虚拟键盘"</string>
<string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"配置实体键盘"</string>
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"点按即可选择语言和布局"</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> 个文件</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"无法使用直接分享功能"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"应用列表"</string>
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index cb62339..302fb71 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -227,7 +227,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"緊急"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"錯誤報告"</string>
<string name="global_action_logout" msgid="935179188218826050">"結束工作階段"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"擷取螢幕畫面"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"螢幕截圖"</string>
<string name="bugreport_title" msgid="5981047024855257269">"錯誤報告"</string>
<string name="bugreport_message" msgid="398447048750350456">"這會收集您目前裝置狀態的相關資訊,並以電郵傳送給您。從開始建立錯誤報告到準備傳送需要一段時間,請耐心等候。"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"互動報告"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"請重新註冊臉孔。"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"無法再識別臉孔。請再試一次。"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"臉孔位置太相近,請改變您的姿勢。"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"請以更直視的角度看著螢幕。"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"請以更直視的角度看著螢幕。"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"請保持頭部垂直。"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"請移除頭部與手機之間的障礙物。"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"請清潔相機。"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"減少頭部左右轉動幅度。"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"減少頭部上下轉動幅度。"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"減少頭部左右轉動幅度。"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"移除遮住您臉孔的任何東西。"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"請清潔螢幕頂部邊緣的感應器。"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"無法驗證臉孔,硬件無法使用。"</string>
@@ -1595,7 +1595,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"無線螢幕分享"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"投放"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"連接裝置"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"在裝置上放送螢幕"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"螢幕投放到裝置"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"正在搜尋裝置…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"設定"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"停止連接"</string>
@@ -2027,4 +2027,5 @@
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> 個檔案</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"無法直接分享"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"應用程式清單"</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 70bc10d..2f5f8a5 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"請重新註冊你的臉孔。"</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"已無法辨識臉孔,請再試一次。"</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"與先前的姿勢太相似,請換一個姿勢。"</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"請直視螢幕。"</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"請直視螢幕。"</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"請將頭擺正。"</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"請清除頭部與手機之間的障礙物。"</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"請清理鏡頭。"</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"請將你的頭部稍微向左或向右轉動。"</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"請將你的頭部稍微向上或向下傾斜。"</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"請將你的頭部稍微向左或向右旋轉。"</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"請移除任何會遮住臉孔的物體。"</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"請清除螢幕頂端感應器的髒汙。"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"相關硬體無法使用,因此無法驗證臉孔。"</string>
@@ -1595,7 +1595,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"無線螢幕分享"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"投放"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"連線至裝置"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"將螢幕投放到裝置上"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"將螢幕畫面投放到裝置上"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"正在搜尋裝置..."</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"設定"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"中斷連線"</string>
@@ -2027,4 +2027,5 @@
<item quantity="one">「<xliff:g id="FILE_NAME_0">%s</xliff:g>」及另外 <xliff:g id="COUNT_1">%d</xliff:g> 個檔案</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"無法使用直接分享功能"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"應用程式清單"</string>
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 933bd41..42056af 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -304,7 +304,7 @@
<string name="permgrouprequest_camera" msgid="1299833592069671756">"Vumela i-<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ukuthatha izithombe iphinde irekhode ividiyo?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Amarekhodi wamakholi"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"funda futhi ubhale irekhodi lamakholi efoni"</string>
- <string name="permgrouprequest_calllog" msgid="8487355309583773267">"Vumela i-<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ukufinyelela irekhodi lakho lamakholi wefoni?"</string>
+ <string name="permgrouprequest_calllog" msgid="8487355309583773267">"Vumela i-<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ukufinyelela kurekhodi lakho lamakholi wefoni?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Ifoni"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"yenza uphinde uphathe amakholi wefoni"</string>
<string name="permgrouprequest_phone" msgid="9166979577750581037">"Vumela i-<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ukuthi yenze iphinde iphathe amakholi efoni?"</string>
@@ -571,11 +571,11 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Sicela uphinde ubhalise ubuso bakho."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Ayisakwazi ukubona ubuso. Zama futhi."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"Kufana kakhulu, sicela ushintshe ukuma kwakho."</string>
- <string name="face_acquired_pan_too_extreme" msgid="1852495480382773759">"Sicela ubheke ngokuqondile kakhulu kusikrini."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="1290820400317982049">"Sicela ubheke ngokuqondile kakhulu kusikrini."</string>
- <string name="face_acquired_roll_too_extreme" msgid="1444829237745898619">"Sicela uqondise ikhanda lakho ngokumile."</string>
- <string name="face_acquired_obscured" msgid="5747521031647744553">"Susa isikhala esiphakathi kwekhanda lakho nefoni."</string>
- <string name="face_acquired_sensor_dirty" msgid="364493868630891300">"Sicela uhlanze ikhamera."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Jikisa ikhanda lakho kancane."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Jikisa ikhanda lakho kancane."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Jikisa ikhanda lakho kancane."</string>
+ <string name="face_acquired_obscured" msgid="5357207702967893283">"Susa noma yini efihle ubuso bakho."</string>
+ <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Hlanza inzwa kunqenqema oluphezulu lwesikrini."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Ayikwazi ukuqinisekisa ubuso. Izingxenyekazi zekhompyutha azitholakali."</string>
@@ -2027,4 +2027,5 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> amafayela</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="997970693708458895">"Ukwabelana okuqondile akutholakali"</string>
+ <string name="chooser_all_apps_button_label" msgid="3631524352936289457">"Uhlu lwezinhlelo zokusebenza"</string>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 489a08a..dbde79b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -87,6 +87,8 @@
theme does not set this value, meaning it is based on whether the
window is floating. -->
<attr name="backgroundDimEnabled" format="boolean" />
+ <!-- Color of background imagery used for popup windows. -->
+ <attr name="colorPopupBackground" format="color" />
<!-- =========== -->
<!-- Text styles -->
@@ -343,8 +345,7 @@
<!-- Drawable to draw selectively within the inset areas when the windowBackground
has been set to null. This protects against seeing visual garbage in the
surface when the app has not drawn any content into this area. One example is
- when the user is resizing a window of an activity that has
- {@link android.R.attr#resizeableActivity} set for multi-window mode. -->
+ when the user is resizing a window of an activity in multi-window mode. -->
<attr name="windowBackgroundFallback" format="reference|color" />
<!-- Drawable to use as a frame around the window. -->
<attr name="windowFrame" format="reference" />
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f9c9c53..8dfb969 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1325,7 +1325,7 @@
<p>The default value of this attribute is <code>false</code>. -->
<attr name="resumeWhilePausing" format="boolean" />
- <!-- Indicates that it is okay for this activity to be resized to any dimension. Intended for a
+ <!-- Indicates that it is okay for this activity to be put in multi-window mode. Intended for a
multi-window device where there can be multiple activities of various sizes on the screen
at the same time.
@@ -1333,6 +1333,12 @@
<code>targetSdkVersion</code> lesser than {@link android.os.Build.VERSION_CODES#N} and
<code>true</code> otherwise.
+ <p>Setting this flag to <code>false</code> lets the system know that the app may not be
+ tested or optimized for multi-window environment. The system may still put such activity in
+ multi-window with compatibility mode applied. It also does not guarantee that there will be
+ no other apps in multi-window visible on screen (e.g. picture-in-picture) or on other
+ displays. Therefore, this flag cannot be used to assure an exclusive resource access.
+
<p>NOTE: A task's root activity value is applied to all additional activities launched in
the task. That is if the root activity of a task is resizeable then the system will treat
all other activities in the task as resizeable and will not if the root activity isn't
@@ -1363,8 +1369,7 @@
Value needs to be greater or equal to 1.0, otherwise it is ignored.
<p>
NOTE: This attribute is ignored if the activity has
- {@link android.R.attr#resizeableActivity} set to true, since that means your activity
- supports any size. -->
+ {@link android.R.attr#resizeableActivity} set to true. -->
<attr name="maxAspectRatio" format="float" />
<!-- This value indicates the minimum aspect ratio the activity supports. If the app runs on a
@@ -1377,8 +1382,7 @@
Value needs to be greater or equal to 1.0, otherwise it is ignored.
<p>
NOTE: This attribute is ignored if the activity has
- {@link android.R.attr#resizeableActivity} set to true, since that means your activity
- supports any size. -->
+ {@link android.R.attr#resizeableActivity} set to true. -->
<attr name="minAspectRatio" format="float" />
<!-- This value indicates how tasks rooted at this activity will behave in lockTask mode.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ccf8509..0daebd7 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -358,6 +358,22 @@
default value of that setting. -->
<integer translatable="false" name="config_networkDefaultDailyMultipathQuotaBytes">2500000</integer>
+ <!-- Default supported concurrent socket keepalive slots per transport type, used by
+ ConnectivityManager.createSocketKeepalive() for calculating the number of keepalive
+ offload slots that should be reserved for privileged access. This string array should be
+ overridden by the device to present the capability of creating socket keepalives. -->
+ <!-- An Array of "[NetworkCapabilities.TRANSPORT_*],[supported keepalives] -->
+ <string-array translatable="false" name="config_networkSupportedKeepaliveCount">
+ <item>0,3</item>
+ <item>1,3</item>
+ </string-array>
+
+ <!-- Reserved privileged keepalive slots per transport. -->
+ <integer translatable="false" name="config_reservedPrivilegedKeepaliveSlots">2</integer>
+
+ <!-- Allowed unprivileged keepalive slots per uid. -->
+ <integer translatable="false" name="config_allowedUnprivilegedKeepalivePerUid">2</integer>
+
<!-- List of regexpressions describing the interface (if any) that represent tetherable
USB interfaces. If the device doesn't want to support tethering over USB this should
be empty. An example would be "usb.*" -->
@@ -1094,6 +1110,11 @@
-->
</integer-array>
+ <!-- Color mode to use when accessibility transforms are enabled. This color mode must be
+ supported by the device, but not necessarily appear in config_availableColorModes. The
+ regularly selected color mode will be used if this value is negative. -->
+ <integer name="config_accessibilityColorMode">-1</integer>
+
<!-- Indicate whether to allow the device to suspend when the screen is off
due to the proximity sensor. This resource should only be set to true
if the sensor HAL correctly handles the proximity sensor as a wake-up source.
@@ -1257,6 +1278,8 @@
<bool name="config_use_strict_phone_number_comparation">false</bool>
+ <bool name="config_use_strict_phone_number_comparation_for_russian">true</bool>
+
<!-- Display low battery warning when battery level dips to this value.
Also, the battery stats are flushed to disk when we hit this level. -->
<integer name="config_criticalBatteryWarningLevel">5</integer>
@@ -3268,6 +3291,10 @@
<!-- Controls whether the navigation bar lets through taps. -->
<bool name="config_navBarTapThrough">false</bool>
+ <!-- Controls whether the side edge gestures can always trigger the transient nav bar to
+ show. -->
+ <bool name="config_navBarAlwaysShowOnSideEdgeGesture">false</bool>
+
<!-- Controls the size of the back gesture inset. -->
<dimen name="config_backGestureInset">0dp</dimen>
@@ -3275,6 +3302,10 @@
{@link Window#setEnsuringNavigationBarContrastWhenTransparent}. -->
<bool name="config_navBarNeedsScrim">true</bool>
+ <!-- Controls whether seamless rotation should be allowed even though the navbar can move
+ (which normally prevents seamless rotation). -->
+ <bool name="config_allowSeamlessRotationDespiteNavBarMoving">false</bool>
+
<!-- Default insets [LEFT/RIGHTxTOP/BOTTOM] from the screen edge for picture-in-picture windows.
These values are in DPs and will be converted to pixel sizes internally. -->
<string translatable="false" name="config_defaultPictureInPictureScreenEdgeInsets">16x16</string>
@@ -3322,9 +3353,8 @@
-->
<integer name="config_dockedStackDividerSnapMode">0</integer>
- <!-- The maximum aspect ratio (longerSide/shorterSide) that is treated as close-to-square. If
- config_forceDefaultOrientation is set to true, the rotation on a close-to-square display
- will be fixed. -->
+ <!-- The maximum aspect ratio (longerSide/shorterSide) that is treated as close-to-square. The
+ orientation requests from apps would be ignored if the display is close-to-square. -->
<item name="config_closeToSquareDisplayMaxAspectRatio" format="float" type="dimen">1.333</item>
<!-- List of comma separated package names for which we the system will not show crash, ANR,
@@ -3693,7 +3723,7 @@
<item name="config_inCallNotificationVolume" format="float" type="dimen">.10</item>
<!-- URI for in call notification sound -->
- <string translatable="false" name="config_inCallNotificationSound">/system/media/audio/ui/InCallNotification.ogg</string>
+ <string translatable="false" name="config_inCallNotificationSound">/product/media/audio/ui/InCallNotification.ogg</string>
<!-- Default number of notifications from the same app before they are automatically grouped by the OS -->
<integer translatable="false" name="config_autoGroupAtCount">4</integer>
@@ -4087,4 +4117,8 @@
<integer-array name="config_face_acquire_vendor_biometricprompt_ignorelist" translatable="false" >
</integer-array>
+ <!-- The component name for the default profile supervisor, which can be set as a profile owner
+ even after user setup is complete. The defined component should be used for supervision purposes
+ only. The component must be part of a system app. -->
+ <string name="config_defaultSupervisionProfileOwnerComponent" translatable="false"></string>
</resources>
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
index f22a91f..12a9ea2 100644
--- a/core/res/res/values/dimens_car.xml
+++ b/core/res/res/values/dimens_car.xml
@@ -137,4 +137,15 @@
<!-- Dialog image margin start -->
<dimen name="image_margin_start">@*android:dimen/car_keyline_1</dimen>
+ <dimen name="car_preference_icon_size">@dimen/car_primary_icon_size</dimen>
+ <dimen name="car_preference_category_icon_size">@dimen/car_primary_icon_size</dimen>
+ <dimen name="car_preference_row_vertical_margin">@dimen/car_padding_2</dimen>
+
+ <!-- Action bar -->
+ <dimen name="action_bar_margin">@*android:dimen/car_margin</dimen>
+ <dimen name="action_bar_margin_start">@*android:dimen/car_margin</dimen>
+ <dimen name="action_bar_margin_end">@*android:dimen/car_margin</dimen>
+ <!-- Space between a button and another button or screen edge -->
+ <dimen name="action_bar_button_margin">@*android:dimen/car_padding_4</dimen>
+ <dimen name="action_bar_toggle_internal_padding">@*android:dimen/car_padding_3</dimen>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 75fd3a0..7de6ca5 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -633,8 +633,8 @@
<!-- Text shown when viewing channel settings for notifications related to vpn status -->
<string name="notification_channel_vpn">VPN status</string>
- <!-- Text shown when viewing channel settings for notifications related to remote device administration -->
- <string name="notification_channel_device_admin">Device administration</string>
+ <!-- Notification channel name. This channel sends high-priority alerts from the user's IT admin for key updates about the user's work device or work profile. -->
+ <string name="notification_channel_device_admin">Alerts from your IT admin</string>
<!-- Text shown when viewing channel settings for notifications related to important alerts -->
<string name="notification_channel_alerts">Alerts</string>
@@ -1533,7 +1533,7 @@
<!-- Message shown during face acquisition when only the left part of the user's face was detected [CHAR LIMIT=50] -->
<string name="face_acquired_too_left">Move phone to the right.</string>
<!-- Message shown during face acquisition when the user is not front facing the sensor [CHAR LIMIT=50] -->
- <string name="face_acquired_poor_gaze">Look at the screen with your eyes open.</string>
+ <string name="face_acquired_poor_gaze">Please look more directly at your device.</string>
<!-- Message shown during face acquisition when the user is not detected [CHAR LIMIT=50] -->
<string name="face_acquired_not_detected">Can\u2019t see your face. Look at the phone.</string>
<!-- Message shown during face acquisition when the device is not steady [CHAR LIMIT=50] -->
@@ -1545,15 +1545,15 @@
<!-- Message shown during face enrollment when the face is too similar to a previous acquisition [CHAR LIMIT=50] -->
<string name="face_acquired_too_similar">Too similar, please change your pose.</string>
<!-- Message shown during acqusition when the user's face is turned too far left or right [CHAR LIMIT=50] -->
- <string name="face_acquired_pan_too_extreme">Please look more directly at the screen.</string>
+ <string name="face_acquired_pan_too_extreme">Turn your head a little less.</string>
<!-- Message shown during acqusition when the user's face is tilted too high or too low [CHAR LIMIT=50] -->
- <string name="face_acquired_tilt_too_extreme">Please look more directly at the screen.</string>
+ <string name="face_acquired_tilt_too_extreme">Turn your head a little less.</string>
<!-- Message shown during acquisiton when the user's face is tilted too far left or right [CHAR LIMIT=50] -->
- <string name="face_acquired_roll_too_extreme">Please straighten your head vertically.</string>
+ <string name="face_acquired_roll_too_extreme">Turn your head a little less.</string>
<!-- Message shown during acquisition when the user's face is obscured [CHAR LIMIT=50] -->
- <string name="face_acquired_obscured">Clear the space between your head and the phone.</string>
+ <string name="face_acquired_obscured">Remove anything hiding your face.</string>
<!-- Message shown during acquisition when the sensor is dirty [CHAR LIMIT=50] -->
- <string name="face_acquired_sensor_dirty">Please clean the camera.</string>
+ <string name="face_acquired_sensor_dirty">Clean the sensor at the top edge of the screen.</string>
<!-- Array containing custom messages shown during face acquisition from vendor. Vendor is expected to add and translate these strings -->
<string-array name="face_acquired_vendor">
</string-array>
@@ -1726,6 +1726,11 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_access_notification_policy">Allows the app to read and write Do Not Disturb configuration.</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_startViewPermissionUsage">start view permission usage</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_startViewPermissionUsage">Allows the holder to start the permission usage for an app. Should never be needed for normal apps.</string>
+
<!-- Policy administration -->
<!-- Title of policy access to limiting the user's password choices -->
@@ -5035,13 +5040,8 @@
<!-- Notification content shown when new SMS/MMS is received while the device is locked [CHAR LIMIT=NONE] -->
<string name="new_sms_notification_content">Open SMS app to view</string>
- <!-- Notification title shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
- <string name="user_encrypted_title">Some functionality may be limited</string>
- <!-- Notification message shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
- <string name="user_encrypted_message">Tap to unlock</string>
- <!-- Notification detail shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
- <string name="user_encrypted_detail">User data locked</string>
-
+ <!-- Notification title shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=36] -->
+ <string name="profile_encrypted_title">Some functionality may be limited</string>
<!-- Notification detail shown when work profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
<string name="profile_encrypted_detail">Work profile locked</string>
<!-- Notification message shown when work profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
diff --git a/core/res/res/values/styles_car.xml b/core/res/res/values/styles_car.xml
index 2129734..d2f5cbb 100644
--- a/core/res/res/values/styles_car.xml
+++ b/core/res/res/values/styles_car.xml
@@ -86,4 +86,19 @@
<item name="textColor">@color/car_title_light</item>
</style>
+ <!-- Action bar -->
+ <style name="ActionBarButton"
+ parent="@style/Widget.DeviceDefault.Button.Borderless.Colored">
+ <item name="android:textAppearance">@style/ActionBarButtonTextAppearance</item>
+ <!-- Button's internal horizontal padding -->
+ <item name="android:paddingStart">@*android:dimen/car_padding_3</item>
+ <item name="android:paddingEnd">@*android:dimen/car_padding_3</item>
+ <item name="android:drawablePadding">@*android:dimen/car_padding_2</item>
+ </style>
+
+ <style name="ActionBarButtonTextAppearance"
+ parent="@style/TextAppearance.DeviceDefault.Widget.Button.Borderless.Colored">
+ <item name="android:singleLine">true</item>
+ <item name="android:textAllCaps">false</item>
+ </style>
</resources>
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index b716ab9..c63be7b 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -68,20 +68,32 @@
<style name="Widget.DeviceDefault.HorizontalScrollView" parent="Widget.Material.HorizontalScrollView"/>
<style name="Widget.DeviceDefault.Spinner" parent="Widget.Material.Spinner"/>
<style name="Widget.DeviceDefault.CompoundButton.Star" parent="Widget.Material.CompoundButton.Star"/>
- <style name="Widget.DeviceDefault.TabWidget" parent="Widget.Material.TabWidget"/>
+ <style name="Widget.DeviceDefault.TabWidget" parent="Widget.Material.TabWidget">
+ <item name="textAppearance">@style/TextAppearance.DeviceDefault.Widget.TabWidget</item>
+ </style>
<style name="Widget.DeviceDefault.WebTextView" parent="Widget.Material.WebTextView"/>
<style name="Widget.DeviceDefault.WebView" parent="Widget.Material.WebView"/>
- <style name="Widget.DeviceDefault.DropDownItem" parent="Widget.Material.DropDownItem"/>
- <style name="Widget.DeviceDefault.DropDownItem.Spinner" parent="Widget.Material.DropDownItem.Spinner"/>
- <style name="Widget.DeviceDefault.TextView.SpinnerItem" parent="Widget.Material.TextView.SpinnerItem"/>
+ <style name="Widget.DeviceDefault.DropDownItem" parent="Widget.Material.DropDownItem">
+ <item name="textAppearance">@style/TextAppearance.DeviceDefault.Widget.DropDownItem</item>
+ </style>
+ <style name="Widget.DeviceDefault.DropDownItem.Spinner" parent="Widget.DeviceDefault.DropDownItem"/>
+ <style name="Widget.DeviceDefault.TextView.SpinnerItem" parent="Widget.Material.TextView.SpinnerItem">
+ <item name="textAppearance">@style/TextAppearance.DeviceDefault.Widget.TextView.SpinnerItem</item>
+ </style>
<style name="Widget.DeviceDefault.ListPopupWindow" parent="Widget.Material.ListPopupWindow"/>
<style name="Widget.DeviceDefault.PopupMenu" parent="Widget.Material.PopupMenu"/>
<style name="Widget.DeviceDefault.ActionButton" parent="Widget.Material.ActionButton"/>
<style name="Widget.DeviceDefault.ActionButton.Overflow" parent="Widget.Material.ActionButton.Overflow"/>
<style name="Widget.DeviceDefault.ActionButton.TextButton" parent="Widget.Material.ActionButton"/>
- <style name="Widget.DeviceDefault.ActionMode" parent="Widget.Material.ActionMode"/>
+ <style name="Widget.DeviceDefault.ActionMode" parent="Widget.Material.ActionMode">
+ <item name="titleTextStyle">@style/TextAppearance.DeviceDefault.Widget.ActionMode.Title</item>
+ <item name="subtitleTextStyle">@style/TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle</item>
+ </style>
<style name="Widget.DeviceDefault.ActionButton.CloseMode" parent="Widget.Material.ActionButton.CloseMode"/>
- <style name="Widget.DeviceDefault.ActionBar" parent="Widget.Material.ActionBar"/>
+ <style name="Widget.DeviceDefault.ActionBar" parent="Widget.Material.ActionBar">
+ <item name="titleTextStyle">@style/TextAppearance.DeviceDefault.Widget.ActionBar.Title</item>
+ <item name="subtitleTextStyle">@style/TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle</item>
+ </style>
<style name="Widget.DeviceDefault.Button.Borderless" parent="Widget.Material.Button.Borderless"/>
<!-- Colored borderless ink button -->
<style name="Widget.DeviceDefault.Button.Borderless.Colored">
@@ -96,10 +108,15 @@
<style name="Widget.DeviceDefault.CalendarView" parent="Widget.Material.CalendarView"/>
<style name="Widget.DeviceDefault.DatePicker" parent="Widget.Material.DatePicker"/>
<style name="Widget.DeviceDefault.ActionBar.TabView" parent="Widget.Material.ActionBar.TabView"/>
- <style name="Widget.DeviceDefault.ActionBar.TabText" parent="Widget.Material.ActionBar.TabText"/>
+ <style name="Widget.DeviceDefault.ActionBar.TabText" parent="Widget.Material.ActionBar.TabText">
+ <item name="titleTextStyle">@style/TextAppearance.DeviceDefault.Widget.ActionBar.Title</item>
+ <item name="subtitleTextStyle">@style/TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle</item>
+ <item name="textAppearance">@style/TextAppearance.DeviceDefault.Widget.TabWidget</item>
+ </style>
<style name="Widget.DeviceDefault.ActionBar.TabBar" parent="Widget.Material.ActionBar.TabBar"/>
<style name="Widget.DeviceDefault.ActionBar.Solid" parent="Widget.Material.ActionBar.Solid">
<item name="titleTextStyle">@style/TextAppearance.DeviceDefault.Widget.ActionBar.Title</item>
+ <item name="subtitleTextStyle">@style/TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle</item>
<item name="background">?attr/colorPrimaryDark</item>
<item name="backgroundStacked">?attr/colorPrimaryDark</item>
<item name="backgroundSplit">?attr/colorPrimaryDark</item>
@@ -108,7 +125,9 @@
<style name="Widget.DeviceDefault.AbsListView" parent="Widget.Material.AbsListView"/>
<style name="Widget.DeviceDefault.Spinner.DropDown.ActionBar" parent="Widget.Material.Spinner.DropDown.ActionBar"/>
<style name="Widget.DeviceDefault.PopupWindow.ActionMode" parent="Widget.Material.PopupWindow.ActionMode"/>
- <style name="Widget.DeviceDefault.CompoundButton.Switch" parent="Widget.Material.CompoundButton.Switch"/>
+ <style name="Widget.DeviceDefault.CompoundButton.Switch" parent="Widget.Material.CompoundButton.Switch">
+ <item name="switchTextAppearance">@style/TextAppearance.DeviceDefault.Widget.Switch</item>
+ </style>
<style name="Widget.DeviceDefault.ExpandableListView.White" parent="Widget.Material.ExpandableListView.White"/>
<style name="Widget.DeviceDefault.FastScroll" parent="Widget.Material.FastScroll"/>
<!-- The FragmentBreadCrumbs widget is deprecated starting in API level 21 ({@link android.os.Build.VERSION_CODES#.L}). -->
@@ -146,8 +165,8 @@
<style name="Widget.DeviceDefault.TimePicker" parent="Widget.Material.TimePicker"/>
<style name="Widget.DeviceDefault.Toolbar" parent="Widget.Material.Toolbar">
<item name="titleTextAppearance">@style/TextAppearance.DeviceDefault.Widget.Toolbar.Title</item>
+ <item name="subtitleTextAppearance">@style/TextAppearance.DeviceDefault.Widget.Toolbar.Subtitle</item>
</style>
-
<style name="Widget.DeviceDefault.Light" parent="Widget.Material.Light"/>
<style name="Widget.DeviceDefault.Light.Button" parent="Widget.Material.Light.Button"/>
<style name="Widget.DeviceDefault.Light.Button.Small" parent="Widget.Material.Light.Button.Small"/>
@@ -186,12 +205,12 @@
<style name="Widget.DeviceDefault.Light.HorizontalScrollView" parent="Widget.Material.Light.HorizontalScrollView"/>
<style name="Widget.DeviceDefault.Light.Spinner" parent="Widget.Material.Light.Spinner"/>
<style name="Widget.DeviceDefault.Light.CompoundButton.Star" parent="Widget.Material.Light.CompoundButton.Star"/>
- <style name="Widget.DeviceDefault.Light.TabWidget" parent="Widget.Material.Light.TabWidget"/>
+ <style name="Widget.DeviceDefault.Light.TabWidget" parent="Widget.DeviceDefault.TabWidget"/>
<style name="Widget.DeviceDefault.Light.WebTextView" parent="Widget.Material.Light.WebTextView"/>
<style name="Widget.DeviceDefault.Light.WebView" parent="Widget.Material.Light.WebView"/>
- <style name="Widget.DeviceDefault.Light.DropDownItem" parent="Widget.Material.Light.DropDownItem"/>
- <style name="Widget.DeviceDefault.Light.DropDownItem.Spinner" parent="Widget.Material.Light.DropDownItem.Spinner"/>
- <style name="Widget.DeviceDefault.Light.TextView.SpinnerItem" parent="Widget.Material.Light.TextView.SpinnerItem"/>
+ <style name="Widget.DeviceDefault.Light.DropDownItem" parent="Widget.DeviceDefault.DropDownItem"/>
+ <style name="Widget.DeviceDefault.Light.DropDownItem.Spinner" parent="Widget.DeviceDefault.DropDownItem.Spinner"/>
+ <style name="Widget.DeviceDefault.Light.TextView.SpinnerItem" parent="Widget.DeviceDefault.TextView.SpinnerItem"/>
<style name="Widget.DeviceDefault.Light.ListPopupWindow" parent="Widget.Material.Light.ListPopupWindow"/>
<style name="Widget.DeviceDefault.Light.PopupMenu" parent="Widget.Material.Light.PopupMenu"/>
<style name="Widget.DeviceDefault.Light.Tab" parent="Widget.Material.Light.Tab"/>
@@ -199,14 +218,15 @@
<style name="Widget.DeviceDefault.Light.Button.Borderless.Small" parent="Widget.Material.Light.Button.Borderless.Small"/>
<style name="Widget.DeviceDefault.Light.ActionButton" parent="Widget.Material.Light.ActionButton"/>
<style name="Widget.DeviceDefault.Light.ActionButton.Overflow" parent="Widget.Material.Light.ActionButton.Overflow"/>
- <style name="Widget.DeviceDefault.Light.ActionMode" parent="Widget.Material.Light.ActionMode"/>
+ <style name="Widget.DeviceDefault.Light.ActionMode" parent="Widget.DeviceDefault.ActionMode"/>
<style name="Widget.DeviceDefault.Light.ActionButton.CloseMode" parent="Widget.Material.Light.ActionButton.CloseMode"/>
- <style name="Widget.DeviceDefault.Light.ActionBar" parent="Widget.Material.Light.ActionBar"/>
- <style name="Widget.DeviceDefault.Light.ActionBar.TabView" parent="Widget.Material.Light.ActionBar.TabView"/>
- <style name="Widget.DeviceDefault.Light.ActionBar.TabText" parent="Widget.Material.Light.ActionBar.TabText"/>
- <style name="Widget.DeviceDefault.Light.ActionBar.TabBar" parent="Widget.Material.Light.ActionBar.TabBar"/>
+ <style name="Widget.DeviceDefault.Light.ActionBar" parent="Widget.DeviceDefault.ActionBar"/>
+ <style name="Widget.DeviceDefault.Light.ActionBar.TabView" parent="Widget.DeviceDefault.ActionBar.TabView" />
+ <style name="Widget.DeviceDefault.Light.ActionBar.TabText" parent="Widget.DeviceDefault.ActionBar.TabText" />
+ <style name="Widget.DeviceDefault.Light.ActionBar.TabBar" parent="Widget.DeviceDefault.ActionBar.TabBar" />
<style name="Widget.DeviceDefault.Light.ActionBar.Solid" parent="Widget.Material.Light.ActionBar.Solid">
<item name="titleTextStyle">@style/TextAppearance.DeviceDefault.Widget.ActionBar.Title</item>
+ <item name="subtitleTextStyle">@style/TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle</item>
</style>
<!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
<style name="Widget.DeviceDefault.Light.ActionBar.Solid.Inverse" parent="Widget.Holo.Light.ActionBar.Solid.Inverse"/>
@@ -307,6 +327,9 @@
<style name="TextAppearance.DeviceDefault.Widget.EditText" parent="TextAppearance.Material.Widget.EditText">
<item name="fontFamily">@string/config_bodyFontFamily</item>
</style>
+ <style name="TextAppearance.DeviceDefault.Widget.Switch" parent="TextAppearance.Material.Widget.Switch">
+ <item name="fontFamily">@string/config_bodyFontFamilyMedium</item>
+ </style>
<style name="TextAppearance.DeviceDefault.Widget.Button.Borderless.Colored" parent="TextAppearance.DeviceDefault.Widget.Button">
<item name="textColor">@color/btn_colored_borderless_text_material</item>
</style>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 35113ed..1ef2eb4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -313,6 +313,7 @@
<java-symbol type="bool" name="config_ui_enableFadingMarquee" />
<java-symbol type="bool" name="config_enableHapticTextHandle" />
<java-symbol type="bool" name="config_use_strict_phone_number_comparation" />
+ <java-symbol type="bool" name="config_use_strict_phone_number_comparation_for_russian" />
<java-symbol type="bool" name="config_single_volume" />
<java-symbol type="bool" name="config_voice_capable" />
<java-symbol type="bool" name="config_requireCallCapableAccountForHandle" />
@@ -1406,6 +1407,10 @@
<java-symbol type="drawable" name="ic_wifi_signal_2" />
<java-symbol type="drawable" name="ic_wifi_signal_3" />
<java-symbol type="drawable" name="ic_wifi_signal_4" />
+ <java-symbol type="drawable" name="ic_signal_wifi_transient_animation" />
+ <java-symbol type="drawable" name="ic_hotspot_transient_animation" />
+ <java-symbol type="drawable" name="ic_bluetooth_transient_animation" />
+ <java-symbol type="drawable" name="ic_signal_cellular" />
<java-symbol type="drawable" name="stat_notify_rssi_in_range" />
<java-symbol type="drawable" name="stat_sys_gps_on" />
<java-symbol type="drawable" name="stat_sys_tether_wifi" />
@@ -2021,6 +2026,9 @@
<java-symbol type="array" name="config_apfEthTypeBlackList" />
<java-symbol type="integer" name="config_networkDefaultDailyMultipathQuotaBytes" />
<java-symbol type="integer" name="config_networkMeteredMultipathPreference" />
+ <java-symbol type="array" name="config_networkSupportedKeepaliveCount" />
+ <java-symbol type="integer" name="config_reservedPrivilegedKeepaliveSlots" />
+ <java-symbol type="integer" name="config_allowedUnprivilegedKeepalivePerUid" />
<java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
<java-symbol type="integer" name="config_notificationsBatteryLedOff" />
<java-symbol type="integer" name="config_notificationsBatteryLedOn" />
@@ -2865,7 +2873,9 @@
<java-symbol type="integer" name="config_navBarInteractionMode" />
<java-symbol type="bool" name="config_navBarCanMove" />
<java-symbol type="bool" name="config_navBarTapThrough" />
+ <java-symbol type="bool" name="config_navBarAlwaysShowOnSideEdgeGesture" />
<java-symbol type="bool" name="config_navBarNeedsScrim" />
+ <java-symbol type="bool" name="config_allowSeamlessRotationDespiteNavBarMoving" />
<java-symbol type="dimen" name="config_backGestureInset" />
<java-symbol type="color" name="system_bar_background_semi_transparent" />
@@ -3018,9 +3028,7 @@
<java-symbol type="string" name="now_string_shortest" />
<!-- Encryption notification while accounts are locked by credential encryption -->
- <java-symbol type="string" name="user_encrypted_title" />
- <java-symbol type="string" name="user_encrypted_message" />
- <java-symbol type="string" name="user_encrypted_detail" />
+ <java-symbol type="string" name="profile_encrypted_title" />
<java-symbol type="string" name="profile_encrypted_detail" />
<java-symbol type="string" name="profile_encrypted_message" />
<java-symbol type="drawable" name="ic_user_secure" />
@@ -3179,6 +3187,7 @@
<java-symbol type="array" name="config_nightDisplayColorTemperatureCoefficients" />
<java-symbol type="array" name="config_nightDisplayColorTemperatureCoefficientsNative" />
<java-symbol type="array" name="config_availableColorModes" />
+ <java-symbol type="integer" name="config_accessibilityColorMode" />
<java-symbol type="bool" name="config_displayWhiteBalanceAvailable" />
<java-symbol type="bool" name="config_displayWhiteBalanceEnabledDefault" />
<java-symbol type="integer" name="config_displayWhiteBalanceColorTemperatureMin" />
@@ -3781,4 +3790,8 @@
<java-symbol type="dimen" name="chooser_direct_share_label_placeholder_max_width" />
<java-symbol type="layout" name="chooser_az_label_row" />
<java-symbol type="string" name="chooser_all_apps_button_label" />
+ <java-symbol type="anim" name="resolver_launch_anim" />
+ <java-symbol type="style" name="Animation.DeviceDefault.Activity.Resolver" />
+
+ <java-symbol type="string" name="config_defaultSupervisionProfileOwnerComponent" />
</resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 2e98460..8015a5d 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -216,6 +216,7 @@
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+ <item name="colorPopupBackground">?attr/colorBackgroundFloating</item>
</style>
<style name="Theme.DeviceDefault" parent="Theme.DeviceDefaultBase" />
@@ -943,6 +944,7 @@
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
+ <item name="colorPopupBackground">?attr/colorBackgroundFloating</item>
</style>
<!-- Variant of the DeviceDefault (light) theme that has a solid (opaque) action bar with an
@@ -1665,8 +1667,7 @@
<!-- Theme used for the intent picker activity. -->
<style name="Theme.DeviceDefault.ResolverCommon" parent="Theme.DeviceDefault.DayNight">
- <item name="windowEnterTransition">@empty</item>
- <item name="windowExitTransition">@empty</item>
+ <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Activity.Resolver</item>
<item name="windowIsTranslucent">true</item>
<item name="windowNoTitle">true</item>
<item name="windowBackground">@color/transparent</item>
@@ -1680,6 +1681,14 @@
<item name="navigationBarDividerColor">@color/chooser_row_divider</item>
</style>
+ <style name="Animation.DeviceDefault.Activity.Resolver" parent="Animation.DeviceDefault.Activity">
+ <item name="activityOpenEnterAnimation">@anim/resolver_launch_anim</item>
+ <item name="taskOpenEnterAnimation">@anim/resolver_launch_anim</item>
+ <!-- Handle close for profile switching -->
+ <item name="activityOpenExitAnimation">@anim/resolver_close_anim</item>
+ <item name="taskOpenExitAnimation">@anim/resolver_close_anim</item>
+ </style>
+
<style name="Theme.DeviceDefault.Resolver" parent="Theme.DeviceDefault.ResolverCommon">
<item name="windowLightNavigationBar">true</item>
</style>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 6b7698e..6337db1 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -52,6 +52,7 @@
<item name="secondaryContentAlpha">@dimen/secondary_content_alpha_material_dark</item>
<item name="backgroundDimAmount">0.6</item>
<item name="colorError">@color/error_color_material_dark</item>
+ <item name="colorPopupBackground">?attr/colorBackground</item>
<!-- Text styles -->
<item name="textAppearance">@style/TextAppearance.Material</item>
@@ -422,6 +423,7 @@
<item name="secondaryContentAlpha">@dimen/secondary_content_alpha_material_light</item>
<item name="backgroundDimAmount">0.6</item>
<item name="colorError">@color/error_color_material_light</item>
+ <item name="colorPopupBackground">?attr/colorBackground</item>
<!-- Text styles -->
<item name="textAppearance">@style/TextAppearance.Material</item>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 7163769..a92c500 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -70,7 +70,7 @@
<shortcode country="ca" pattern="\\d{5,6}" premium="60999|88188|43030" standard="244444" />
<!-- Switzerland: 3-5 digits: http://www.swisscom.ch/fxres/kmu/thirdpartybusiness_code_of_conduct_en.pdf -->
- <shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111|30118" free="98765" />
+ <shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111|30118" free="98765|30075" />
<!-- Chile: 4-5 digits (not confirmed), known premium codes listed -->
<shortcode country="cl" pattern="\\d{4,5}" free="9963|9240" />
diff --git a/core/tests/bugreports/Android.bp b/core/tests/bugreports/Android.bp
new file mode 100644
index 0000000..d3bf0dd
--- /dev/null
+++ b/core/tests/bugreports/Android.bp
@@ -0,0 +1,27 @@
+// Copyright (C) 2019 The Android Open 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.
+
+android_test {
+ name: "BugreportManagerTestCases",
+ srcs: ["src/**/*.java"],
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ static_libs: ["androidx.test.rules", "truth-prebuilt"],
+ test_suites: ["general-tests"],
+ sdk_version: "test_current",
+ platform_apis: true,
+}
+
diff --git a/core/tests/bugreports/AndroidManifest.xml b/core/tests/bugreports/AndroidManifest.xml
new file mode 100644
index 0000000..0cfb874
--- /dev/null
+++ b/core/tests/bugreports/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ android:installLocation="internalOnly"
+ package="com.android.os.bugreports.tests">
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.os.bugreports.tests"
+ android:label="Unit tests of BugreportManager" />
+</manifest>
diff --git a/core/tests/bugreports/AndroidTest.xml b/core/tests/bugreports/AndroidTest.xml
new file mode 100644
index 0000000..410ca60
--- /dev/null
+++ b/core/tests/bugreports/AndroidTest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open 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 BugreportManager test cases">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
+ <option name="config-descriptor:metadata" key="component" value="framework"/>
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="test-file-name" value="BugreportManagerTestCases.apk"/>
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.os.bugreports.tests"/>
+ <!-- test-timeout unit is ms, value = 30 min -->
+ <option name="test-timeout" value="1800000" />
+ <option name="runtime-hint" value="30m" />
+ </test>
+</configuration>
diff --git a/core/tests/bugreports/config/test-sysconfig.xml b/core/tests/bugreports/config/test-sysconfig.xml
new file mode 100644
index 0000000..09c69ba
--- /dev/null
+++ b/core/tests/bugreports/config/test-sysconfig.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open 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.
+-->
+
+<!-- WARNING: This is a test config. -->
+<config>
+ <bugreport-whitelisted package="com.android.os.bugreports.tests" />
+</config>
diff --git a/core/tests/bugreports/run.sh b/core/tests/bugreports/run.sh
new file mode 100755
index 0000000..0103398
--- /dev/null
+++ b/core/tests/bugreports/run.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+# Copyright (C) 2019 The Android Open 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.
+
+# Script to run bugreport unitests
+# Must run on a rooted device.
+# Must run lunch before running the script
+# Usage: ${ANDROID_BUILD_TOP}/frameworks/base/core/tests/bugreports/run.sh
+
+# NOTE: This script replaces the framework-sysconfig.xml on your device, so use with caution.
+# It tries to replace it when done, but if the script does not finish cleanly
+# (for e.g. force stopped mid-way) your device will be left in an inconsistent state.
+# Reflashing will restore the right config.
+
+TMP_SYS_CONFIG=/var/tmp/framework-sysconfig.xml
+
+if [[ -z $ANDROID_PRODUCT_OUT ]]; then
+ echo "Please lunch before running this test."
+ exit 0
+fi
+
+# Print every command to console.
+set -x
+
+make -j BugreportManagerTestCases &&
+ adb root &&
+ adb remount &&
+ adb wait-for-device &&
+ # Save the sysconfig file in a tmp location and push the test config in
+ adb pull /system/etc/sysconfig/framework-sysconfig.xml "${TMP_SYS_CONFIG}" &&
+ adb push $ANDROID_BUILD_TOP/frameworks/base/core/tests/bugreports/config/test-sysconfig.xml /system/etc/sysconfig/framework-sysconfig.xml &&
+ # The test app needs to be a priv-app.
+ adb push $OUT/testcases/BugreportManagerTestCases/*/BugreportManagerTestCases.apk /system/priv-app ||
+ exit 1
+
+adb reboot &&
+adb wait-for-device &&
+atest BugreportManagerTest || echo "Tests FAILED!"
+
+# Restore the saved config file
+if [ -f "${TMP_SYS_CONFIG}" ]; then
+ SIZE=$(stat --printf="%s" "${TMP_SYS_CONFIG}")
+ if [ SIZE > 0 ]; then
+ adb remount &&
+ adb wait-for-device &&
+ adb push "${TMP_SYS_CONFIG}" /system/etc/sysconfig/framework-sysconfig.xml &&
+ rm "${TMP_SYS_CONFIG}"
+ fi
+fi
diff --git a/core/tests/bugreports/src/android/server/bugreports/BugreportManagerTest.java b/core/tests/bugreports/src/android/server/bugreports/BugreportManagerTest.java
new file mode 100644
index 0000000..220f854
--- /dev/null
+++ b/core/tests/bugreports/src/android/server/bugreports/BugreportManagerTest.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.os.bugreports.tests;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+
+import android.Manifest;
+import android.content.Context;
+import android.os.BugreportManager;
+import android.os.BugreportManager.BugreportCallback;
+import android.os.BugreportParams;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.File;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * Tests for BugreportManager API.
+ */
+@RunWith(JUnit4.class)
+public class BugreportManagerTest {
+ @Rule public TestName name = new TestName();
+
+ private static final String TAG = "BugreportManagerTest";
+ private static final long BUGREPORT_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(10);
+
+ private Handler mHandler;
+ private Executor mExecutor;
+ private BugreportManager mBrm;
+ private ParcelFileDescriptor mBugreportFd;
+ private ParcelFileDescriptor mScreenshotFd;
+
+ @Before
+ public void setup() throws Exception {
+ mHandler = createHandler();
+ mExecutor = (runnable) -> {
+ if (mHandler != null) {
+ mHandler.post(() -> {
+ runnable.run();
+ });
+ }
+ };
+
+ mBrm = getBugreportManager();
+ mBugreportFd = parcelFd("bugreport_" + name.getMethodName(), ".zip");
+ mScreenshotFd = parcelFd("screenshot_" + name.getMethodName(), ".png");
+
+ getPermissions();
+ }
+
+ @After
+ public void teardown() throws Exception {
+ dropPermissions();
+ }
+
+
+ @Test
+ public void normalFlow_wifi() throws Exception {
+ BugreportCallbackImpl callback = new BugreportCallbackImpl();
+ mBrm.startBugreport(mBugreportFd, mScreenshotFd, wifi(), mExecutor, callback);
+ waitTillDoneOrTimeout(callback);
+
+ assertThat(callback.isDone()).isTrue();
+ // Wifi bugreports should not receive any progress.
+ assertThat(callback.hasReceivedProgress()).isFalse();
+ // TODO: Because of b/130234145, consent dialog is not shown; so we get a timeout error.
+ // When the bug is fixed, accept consent via UIAutomator and verify contents
+ // of mBugreportFd.
+ assertThat(callback.getErrorCode()).isEqualTo(
+ BugreportCallback.BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
+ assertFdsAreClosed(mBugreportFd, mScreenshotFd);
+ }
+
+ @Test
+ public void normalFlow_interactive() throws Exception {
+ BugreportCallbackImpl callback = new BugreportCallbackImpl();
+ mBrm.startBugreport(mBugreportFd, mScreenshotFd, interactive(), mExecutor, callback);
+
+ waitTillDoneOrTimeout(callback);
+ assertThat(callback.isDone()).isTrue();
+ // Interactive bugreports show progress updates.
+ assertThat(callback.hasReceivedProgress()).isTrue();
+ assertThat(callback.getErrorCode()).isEqualTo(
+ BugreportCallback.BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
+ assertFdsAreClosed(mBugreportFd, mScreenshotFd);
+ }
+
+ @Test
+ public void simultaneousBugreportsNotAllowed() throws Exception {
+ // Start bugreport #1
+ BugreportCallbackImpl callback = new BugreportCallbackImpl();
+ mBrm.startBugreport(mBugreportFd, mScreenshotFd, wifi(), mExecutor, callback);
+
+ // Before #1 is done, try to start #2.
+ assertThat(callback.isDone()).isFalse();
+ BugreportCallbackImpl callback2 = new BugreportCallbackImpl();
+ ParcelFileDescriptor bugreportFd2 = parcelFd("bugreport_2_" + name.getMethodName(), ".zip");
+ ParcelFileDescriptor screenshotFd2 =
+ parcelFd("screenshot_2_" + name.getMethodName(), ".png");
+ mBrm.startBugreport(bugreportFd2, screenshotFd2, wifi(), mExecutor, callback2);
+ Thread.sleep(500 /* .5s */);
+
+ // Verify #2 encounters an error.
+ assertThat(callback2.getErrorCode()).isEqualTo(
+ BugreportCallback.BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS);
+ assertFdsAreClosed(bugreportFd2, screenshotFd2);
+
+ // Cancel #1 so we can move on to the next test.
+ mBrm.cancelBugreport();
+ Thread.sleep(500 /* .5s */);
+ assertThat(callback.isDone()).isTrue();
+ assertFdsAreClosed(mBugreportFd, mScreenshotFd);
+ }
+
+ @Test
+ public void cancelBugreport() throws Exception {
+ // Start a bugreport.
+ BugreportCallbackImpl callback = new BugreportCallbackImpl();
+ mBrm.startBugreport(mBugreportFd, mScreenshotFd, wifi(), mExecutor, callback);
+
+ // Verify it's not finished yet.
+ assertThat(callback.isDone()).isFalse();
+
+ // Try to cancel it, but first without DUMP permission.
+ dropPermissions();
+ try {
+ mBrm.cancelBugreport();
+ fail("Expected cancelBugreport to throw SecurityException without DUMP permission");
+ } catch (SecurityException expected) {
+ }
+ assertThat(callback.isDone()).isFalse();
+
+ // Try again, with DUMP permission.
+ getPermissions();
+ mBrm.cancelBugreport();
+ Thread.sleep(500 /* .5s */);
+ assertThat(callback.isDone()).isTrue();
+ assertFdsAreClosed(mBugreportFd, mScreenshotFd);
+ }
+
+ @Test
+ public void insufficientPermissions_throwsException() throws Exception {
+ dropPermissions();
+
+ BugreportCallbackImpl callback = new BugreportCallbackImpl();
+ try {
+ mBrm.startBugreport(mBugreportFd, mScreenshotFd, wifi(), mExecutor, callback);
+ fail("Expected startBugreport to throw SecurityException without DUMP permission");
+ } catch (SecurityException expected) {
+ }
+ assertFdsAreClosed(mBugreportFd, mScreenshotFd);
+ }
+
+ @Test
+ public void invalidBugreportMode_throwsException() throws Exception {
+ BugreportCallbackImpl callback = new BugreportCallbackImpl();
+
+ try {
+ mBrm.startBugreport(mBugreportFd, mScreenshotFd,
+ new BugreportParams(25) /* unknown bugreport mode */, mExecutor, callback);
+ fail("Expected to throw IllegalArgumentException with unknown bugreport mode");
+ } catch (IllegalArgumentException expected) {
+ }
+ assertFdsAreClosed(mBugreportFd, mScreenshotFd);
+ }
+
+ private Handler createHandler() {
+ HandlerThread handlerThread = new HandlerThread("BugreportManagerTest");
+ handlerThread.start();
+ return new Handler(handlerThread.getLooper());
+ }
+
+ /* Implementatiion of {@link BugreportCallback} that offers wrappers around execution result */
+ private static final class BugreportCallbackImpl extends BugreportCallback {
+ private int mErrorCode = -1;
+ private boolean mSuccess = false;
+ private boolean mReceivedProgress = false;
+ private final Object mLock = new Object();
+
+ @Override
+ public void onProgress(float progress) {
+ synchronized (mLock) {
+ mReceivedProgress = true;
+ }
+ }
+
+ @Override
+ public void onError(int errorCode) {
+ synchronized (mLock) {
+ mErrorCode = errorCode;
+ Log.d(TAG, "bugreport errored.");
+ }
+ }
+
+ @Override
+ public void onFinished() {
+ synchronized (mLock) {
+ Log.d(TAG, "bugreport finished.");
+ mSuccess = true;
+ }
+ }
+
+ /* Indicates completion; and ended up with a success or error. */
+ public boolean isDone() {
+ synchronized (mLock) {
+ return (mErrorCode != -1) || mSuccess;
+ }
+ }
+
+ public int getErrorCode() {
+ synchronized (mLock) {
+ return mErrorCode;
+ }
+ }
+
+ public boolean isSuccess() {
+ synchronized (mLock) {
+ return mSuccess;
+ }
+ }
+
+ public boolean hasReceivedProgress() {
+ synchronized (mLock) {
+ return mReceivedProgress;
+ }
+ }
+ }
+
+ public static BugreportManager getBugreportManager() {
+ Context context = InstrumentationRegistry.getContext();
+ BugreportManager bm =
+ (BugreportManager) context.getSystemService(Context.BUGREPORT_SERVICE);
+ if (bm == null) {
+ throw new AssertionError("Failed to get BugreportManager");
+ }
+ return bm;
+ }
+
+ private static ParcelFileDescriptor parcelFd(String prefix, String extension) throws Exception {
+ File f = File.createTempFile(prefix, extension);
+ f.setReadable(true, true);
+ f.setWritable(true, true);
+
+ return ParcelFileDescriptor.open(f,
+ ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_APPEND);
+ }
+
+ private static void dropPermissions() {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ private static void getPermissions() {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(Manifest.permission.DUMP);
+ }
+
+ private static void assertFdIsClosed(ParcelFileDescriptor pfd) {
+ try {
+ int fd = pfd.getFd();
+ fail("Expected ParcelFileDescriptor argument to be closed, but got: " + fd);
+ } catch (IllegalStateException expected) {
+ }
+ }
+
+ private static void assertFdsAreClosed(ParcelFileDescriptor... pfds) {
+ for (int i = 0; i < pfds.length; i++) {
+ assertFdIsClosed(pfds[i]);
+ }
+ }
+
+ private static long now() {
+ return System.currentTimeMillis();
+ }
+
+ private static boolean shouldTimeout(long startTimeMs) {
+ return now() - startTimeMs >= BUGREPORT_TIMEOUT_MS;
+ }
+
+ private static void waitTillDoneOrTimeout(BugreportCallbackImpl callback) throws Exception {
+ long startTimeMs = now();
+ while (!callback.isDone()) {
+ Thread.sleep(1000 /* 1s */);
+ if (shouldTimeout(startTimeMs)) {
+ break;
+ }
+ Log.d(TAG, "Waited " + (now() - startTimeMs) + "ms");
+ }
+ }
+
+ /*
+ * Returns a {@link BugreportParams} for wifi only bugreport.
+ *
+ * <p>Wifi bugreports have minimal content and are fast to run. They also suppress progress
+ * updates.
+ */
+ private static BugreportParams wifi() {
+ return new BugreportParams(BugreportParams.BUGREPORT_MODE_WIFI);
+ }
+
+ /*
+ * Returns a {@link BugreportParams} for interactive bugreport that offers progress updates.
+ *
+ * <p>This is the typical bugreport taken by users. This can take on the order of minutes to
+ * finish.
+ */
+ private static BugreportParams interactive() {
+ return new BugreportParams(BugreportParams.BUGREPORT_MODE_INTERACTIVE);
+ }
+}
diff --git a/core/tests/coretests/res/values/overlayable_icons_test.xml b/core/tests/coretests/res/values/overlayable_icons_test.xml
index 9bc46de..68de2c0 100644
--- a/core/tests/coretests/res/values/overlayable_icons_test.xml
+++ b/core/tests/coretests/res/values/overlayable_icons_test.xml
@@ -27,9 +27,9 @@
<item>@*android:drawable/ic_bt_laptop</item>
<item>@*android:drawable/ic_bt_network_pan</item>
<item>@*android:drawable/ic_bt_pointing_hid</item>
+ <item>@*android:drawable/ic_corp_badge</item>
<item>@*android:drawable/ic_expand_more</item>
<item>@*android:drawable/ic_file_copy</item>
- <item>@*android:drawable/ic_info_outline_24</item>
<item>@*android:drawable/ic_lock</item>
<item>@*android:drawable/ic_lock_bugreport</item>
<item>@*android:drawable/ic_lock_open</item>
@@ -39,6 +39,7 @@
<item>@*android:drawable/ic_phone</item>
<item>@*android:drawable/ic_qs_airplane</item>
<item>@*android:drawable/ic_qs_auto_rotate</item>
+ <item>@*android:drawable/ic_qs_battery_saver</item>
<item>@*android:drawable/ic_qs_bluetooth</item>
<item>@*android:drawable/ic_qs_dnd</item>
<item>@*android:drawable/ic_qs_flashlight</item>
@@ -46,6 +47,17 @@
<item>@*android:drawable/ic_restart</item>
<item>@*android:drawable/ic_screenshot</item>
<item>@*android:drawable/ic_settings_bluetooth</item>
+ <item>@*android:drawable/ic_signal_cellular_0_4_bar</item>
+ <item>@*android:drawable/ic_signal_cellular_0_5_bar</item>
+ <item>@*android:drawable/ic_signal_cellular_1_4_bar</item>
+ <item>@*android:drawable/ic_signal_cellular_1_5_bar</item>
+ <item>@*android:drawable/ic_signal_cellular_2_4_bar</item>
+ <item>@*android:drawable/ic_signal_cellular_2_5_bar</item>
+ <item>@*android:drawable/ic_signal_cellular_3_4_bar</item>
+ <item>@*android:drawable/ic_signal_cellular_3_5_bar</item>
+ <item>@*android:drawable/ic_signal_cellular_4_4_bar</item>
+ <item>@*android:drawable/ic_signal_cellular_4_5_bar</item>
+ <item>@*android:drawable/ic_signal_cellular_5_5_bar</item>
<item>@*android:drawable/ic_signal_location</item>
<item>@*android:drawable/ic_wifi_signal_0</item>
<item>@*android:drawable/ic_wifi_signal_1</item>
@@ -53,6 +65,7 @@
<item>@*android:drawable/ic_wifi_signal_3</item>
<item>@*android:drawable/ic_wifi_signal_4</item>
<item>@*android:drawable/perm_group_activity_recognition</item>
+ <item>@*android:drawable/perm_group_calendar</item>
<item>@*android:drawable/perm_group_call_log</item>
<item>@*android:drawable/perm_group_camera</item>
<item>@*android:drawable/perm_group_contacts</item>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 61fb811..fda37c8 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -636,6 +636,8 @@
Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
Settings.Secure.ENABLED_PRINT_SERVICES,
+ Settings.Secure.GLOBAL_ACTIONS_PANEL_AVAILABLE,
+ Settings.Secure.GLOBAL_ACTIONS_PANEL_DEBUG_ENABLED,
Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
Settings.Secure.INPUT_METHOD_SELECTOR_VISIBILITY,
@@ -695,7 +697,6 @@
Settings.Secure.TV_INPUT_CUSTOM_LABELS,
Settings.Secure.TV_INPUT_HIDDEN_INPUTS,
Settings.Secure.TV_USER_SETUP_COMPLETE,
- Settings.Secure.UI_NIGHT_MODE, // candidate?
Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED,
Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS,
Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED,
@@ -721,7 +722,8 @@
Settings.Secure.LOCATION_ACCESS_CHECK_DELAY_MILLIS,
Settings.Secure.BIOMETRIC_DEBUG_ENABLED,
Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
- Settings.Secure.FACE_UNLOCK_DIVERSITY_REQUIRED);
+ Settings.Secure.FACE_UNLOCK_DIVERSITY_REQUIRED,
+ Settings.Secure.FACE_UNLOCK_EDUCATION_INFO_DISPLAYED);
@Test
public void systemSettingsBackedUpOrBlacklisted() {
@@ -799,4 +801,3 @@
}
}
-
diff --git a/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java b/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java
index 2f17b32..a8ca6f0 100644
--- a/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java
+++ b/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java
@@ -16,7 +16,10 @@
package android.view.autofill;
+import static android.view.autofill.AutofillId.NO_SESSION;
+
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.testng.Assert.assertThrows;
@@ -33,20 +36,10 @@
@Test
public void testNonVirtual() {
final AutofillId id = new AutofillId(42);
- assertThat(id.getViewId()).isEqualTo(42);
- assertThat(id.isNonVirtual()).isTrue();
- assertThat(id.isVirtualInt()).isFalse();
- assertThat(id.isVirtualLong()).isFalse();
- assertThat(id.getVirtualChildIntId()).isEqualTo(View.NO_ID);
- assertThat(id.getVirtualChildLongId()).isEqualTo(View.NO_ID);
+ assertNonVirtual(id, 42, NO_SESSION);
final AutofillId clone = cloneThroughParcel(id);
- assertThat(clone.getViewId()).isEqualTo(42);
- assertThat(clone.isNonVirtual()).isTrue();
- assertThat(clone.isVirtualInt()).isFalse();
- assertThat(clone.isVirtualLong()).isFalse();
- assertThat(clone.getVirtualChildIntId()).isEqualTo(View.NO_ID);
- assertThat(clone.getVirtualChildLongId()).isEqualTo(View.NO_ID);
+ assertNonVirtual(clone, 42, NO_SESSION);
}
@Test
@@ -124,49 +117,174 @@
}
@Test
- public void testEqualsHashCode() {
- final AutofillId realId = new AutofillId(42);
- final AutofillId realIdSame = new AutofillId(42);
- assertThat(realId).isEqualTo(realIdSame);
- assertThat(realIdSame).isEqualTo(realId);
- assertThat(realId.hashCode()).isEqualTo(realIdSame.hashCode());
+ public void testFactoryMethod_withoutSession() {
+ final AutofillId id = new AutofillId(42);
+ id.setSessionId(108);
+ assertNonVirtual(id, 42, 108);
+ final AutofillId idWithoutSession = AutofillId.withoutSession(id);
+ assertNonVirtual(idWithoutSession, 42, NO_SESSION);
+ }
- final AutofillId realIdDifferent = new AutofillId(108);
- assertThat(realId).isNotEqualTo(realIdDifferent);
- assertThat(realIdDifferent).isNotEqualTo(realId);
+ @Test
+ public void testSetResetSession() {
+ final AutofillId id = new AutofillId(42);
+ assertNonVirtual(id, 42, NO_SESSION);
+ id.setSessionId(108);
+ assertNonVirtual(id, 42, 108);
- final AutofillId virtualId = new AutofillId(42, 1);
- final AutofillId virtualIdSame = new AutofillId(42, 1);
- assertThat(virtualId).isEqualTo(virtualIdSame);
- assertThat(virtualIdSame).isEqualTo(virtualId);
- assertThat(virtualId.hashCode()).isEqualTo(virtualIdSame.hashCode());
- assertThat(virtualId).isNotEqualTo(realId);
- assertThat(realId).isNotEqualTo(virtualId);
+ final AutofillId clone1 = cloneThroughParcel(id);
+ assertNonVirtual(clone1, 42, 108);
- final AutofillId virtualIdDifferentChild = new AutofillId(42, 2);
- assertThat(virtualIdDifferentChild).isNotEqualTo(virtualId);
- assertThat(virtualId).isNotEqualTo(virtualIdDifferentChild);
- assertThat(virtualIdDifferentChild).isNotEqualTo(realId);
- assertThat(realId).isNotEqualTo(virtualIdDifferentChild);
+ id.resetSessionId();
+ assertThat(id.getSessionId()).isEqualTo(NO_SESSION);
+ final AutofillId clone2 = cloneThroughParcel(id);
+ assertNonVirtual(clone2, 42, NO_SESSION);
+ }
- final AutofillId virtualIdDifferentParent = new AutofillId(108, 1);
- assertThat(virtualIdDifferentParent).isNotEqualTo(virtualId);
- assertThat(virtualId).isNotEqualTo(virtualIdDifferentParent);
- assertThat(virtualIdDifferentParent).isNotEqualTo(virtualIdDifferentChild);
- assertThat(virtualIdDifferentChild).isNotEqualTo(virtualIdDifferentParent);
+ @Test
+ public void testEqualsHashCode_nonVirtual_same() {
+ final AutofillId id = new AutofillId(42);
+ final AutofillId sameId = new AutofillId(42);
- final AutofillId virtualIdDifferentSession = new AutofillId(new AutofillId(42), 1L, 108);
- assertThat(virtualIdDifferentSession).isNotEqualTo(virtualId);
- assertThat(virtualId).isNotEqualTo(virtualIdDifferentSession);
- assertThat(virtualIdDifferentSession).isNotEqualTo(realId);
- assertThat(realId).isNotEqualTo(virtualIdDifferentSession);
+ assertThat(id).isEqualTo(sameId);
+ assertThat(sameId).isEqualTo(id);
+ assertEqualsIgnoreSession(id, sameId);
+ assertEqualsIgnoreSession(sameId, id);
+ assertThat(id.hashCode()).isEqualTo(sameId.hashCode());
+ }
- final AutofillId sameVirtualIdDifferentSession =
- new AutofillId(new AutofillId(42), 1L, 108);
- assertThat(sameVirtualIdDifferentSession).isEqualTo(virtualIdDifferentSession);
- assertThat(virtualIdDifferentSession).isEqualTo(sameVirtualIdDifferentSession);
- assertThat(sameVirtualIdDifferentSession.hashCode())
- .isEqualTo(virtualIdDifferentSession.hashCode());
+ @Test
+ public void testEqualsHashCode_nonVirtual_other() {
+ final AutofillId id = new AutofillId(42);
+ final AutofillId otherId = new AutofillId(108);
+
+ assertThat(id).isNotEqualTo(otherId);
+ assertThat(otherId).isNotEqualTo(id);
+ assertNotEqualsIgnoreSession(id, otherId);
+ assertNotEqualsIgnoreSession(otherId, id);
+ assertThat(id.hashCode()).isNotEqualTo(otherId.hashCode());
+ }
+
+ @Test
+ public void testEqualsHashCode_virtual_same() {
+ final AutofillId id = new AutofillId(42);
+ final AutofillId virtual = new AutofillId(42, 1);
+ final AutofillId sameVirtual = new AutofillId(42, 1);
+
+ assertThat(virtual).isEqualTo(sameVirtual);
+ assertThat(sameVirtual).isEqualTo(virtual);
+ assertEqualsIgnoreSession(virtual, sameVirtual);
+ assertEqualsIgnoreSession(sameVirtual, virtual);
+ assertThat(virtual.hashCode()).isEqualTo(sameVirtual.hashCode());
+ assertThat(virtual).isNotEqualTo(id);
+ assertThat(id).isNotEqualTo(virtual);
+ assertNotEqualsIgnoreSession(id, virtual);
+ assertNotEqualsIgnoreSession(virtual, id);
+ }
+
+ @Test
+ public void testEqualsHashCode_virtual_otherChild() {
+ final AutofillId id = new AutofillId(42);
+ final AutofillId virtual = new AutofillId(42, 1);
+ final AutofillId virtualOtherChild = new AutofillId(42, 2);
+
+ assertThat(virtualOtherChild).isNotEqualTo(virtual);
+ assertThat(virtual).isNotEqualTo(virtualOtherChild);
+ assertNotEqualsIgnoreSession(virtualOtherChild, virtual);
+ assertNotEqualsIgnoreSession(virtual, virtualOtherChild);
+ assertThat(virtualOtherChild).isNotEqualTo(id);
+ assertThat(id).isNotEqualTo(virtualOtherChild);
+ assertNotEqualsIgnoreSession(virtualOtherChild, id);
+ assertNotEqualsIgnoreSession(id, virtualOtherChild);
+ }
+
+ @Test
+ public void testEqualsHashCode_virtual_otherParent() {
+ final AutofillId virtual = new AutofillId(42, 1);
+ final AutofillId virtualOtherParent = new AutofillId(108, 1);
+ final AutofillId virtualOtherChild = new AutofillId(42, 2);
+
+ assertThat(virtualOtherParent).isNotEqualTo(virtual);
+ assertThat(virtual).isNotEqualTo(virtualOtherParent);
+ assertNotEqualsIgnoreSession(virtualOtherParent, virtual);
+ assertNotEqualsIgnoreSession(virtual, virtualOtherParent);
+ assertThat(virtualOtherParent).isNotEqualTo(virtualOtherChild);
+ assertThat(virtualOtherChild).isNotEqualTo(virtualOtherParent);
+ assertNotEqualsIgnoreSession(virtualOtherParent, virtualOtherChild);
+ assertNotEqualsIgnoreSession(virtualOtherChild, virtualOtherParent);
+ }
+
+ @Test
+ public void testEqualsHashCode_virtual_otherSession() {
+ final AutofillId virtual = new AutofillId(42, 1);
+ final AutofillId virtualOtherSession = new AutofillId(42, 1);
+ virtualOtherSession.setSessionId(666);
+
+ assertThat(virtualOtherSession).isNotEqualTo(virtual);
+ assertThat(virtual).isNotEqualTo(virtualOtherSession);
+ assertEqualsIgnoreSession(virtualOtherSession, virtual);
+ assertEqualsIgnoreSession(virtual, virtualOtherSession);
+ }
+
+ @Test
+ public void testEqualsHashCode_virtual_longId_same() {
+ final AutofillId hostId = new AutofillId(42);
+ final AutofillId virtual = new AutofillId(hostId, 1L, 108);
+ final AutofillId sameVirtual = new AutofillId(hostId, 1L, 108);
+
+ assertThat(sameVirtual).isEqualTo(virtual);
+ assertThat(virtual).isEqualTo(sameVirtual);
+ assertEqualsIgnoreSession(sameVirtual, virtual);
+ assertEqualsIgnoreSession(virtual, sameVirtual);
+ assertThat(sameVirtual).isNotEqualTo(hostId);
+ assertThat(hostId).isNotEqualTo(sameVirtual);
+ assertNotEqualsIgnoreSession(sameVirtual, hostId);
+ assertNotEqualsIgnoreSession(hostId, sameVirtual);
+ }
+
+ @Test
+ public void testEqualsHashCode_virtual_longId_otherChild() {
+ final AutofillId hostId = new AutofillId(42);
+ final AutofillId virtual = new AutofillId(hostId, 1L, 108);
+ final AutofillId virtualOtherChild = new AutofillId(hostId, 2L, 108);
+
+ assertThat(virtualOtherChild).isNotEqualTo(virtual);
+ assertThat(virtual).isNotEqualTo(virtualOtherChild);
+ assertNotEqualsIgnoreSession(virtualOtherChild, virtual);
+ assertNotEqualsIgnoreSession(virtual, virtualOtherChild);
+ assertThat(virtualOtherChild).isNotEqualTo(hostId);
+ assertThat(hostId).isNotEqualTo(virtualOtherChild);
+ assertNotEqualsIgnoreSession(virtualOtherChild, hostId);
+ assertNotEqualsIgnoreSession(hostId, virtualOtherChild);
+ }
+
+ @Test
+ public void testEqualsHashCode_virtual_longId_otherParent() {
+ final AutofillId hostId = new AutofillId(42);
+ final AutofillId virtual = new AutofillId(hostId, 1L, 108);
+ final AutofillId virtualOtherParent = new AutofillId(new AutofillId(666), 1L, 108);
+ final AutofillId virtualOtherChild = new AutofillId(hostId, 2L, 108);
+
+ assertThat(virtualOtherParent).isNotEqualTo(virtual);
+ assertThat(virtual).isNotEqualTo(virtualOtherParent);
+ assertNotEqualsIgnoreSession(virtualOtherParent, virtual);
+ assertNotEqualsIgnoreSession(virtual, virtualOtherParent);
+ assertThat(virtualOtherParent).isNotEqualTo(virtualOtherChild);
+ assertThat(virtualOtherChild).isNotEqualTo(virtualOtherParent);
+ assertNotEqualsIgnoreSession(virtualOtherParent, virtualOtherChild);
+ assertNotEqualsIgnoreSession(virtualOtherChild, virtualOtherParent);
+ }
+
+ @Test
+ public void testEqualsHashCode_virtual_longId_otherSession() {
+ final AutofillId hostId = new AutofillId(42);
+ final AutofillId virtual = new AutofillId(hostId, 1L, 108);
+ final AutofillId virtualOtherSession = new AutofillId(hostId, 1L, 666);
+
+ assertThat(virtualOtherSession).isNotEqualTo(virtual);
+ assertThat(virtual).isNotEqualTo(virtualOtherSession);
+ assertEqualsIgnoreSession(virtualOtherSession, virtual);
+ assertEqualsIgnoreSession(virtual, virtualOtherSession);
}
private AutofillId cloneThroughParcel(AutofillId id) {
@@ -186,4 +304,28 @@
parcel.recycle();
}
}
+
+ private void assertEqualsIgnoreSession(AutofillId id1, AutofillId id2) {
+ assertWithMessage("id1 is null").that(id1).isNotNull();
+ assertWithMessage("id2 is null").that(id2).isNotNull();
+ assertWithMessage("%s is not equal to %s", id1, id2).that(id1.equalsIgnoreSession(id2))
+ .isTrue();
+ }
+
+ private void assertNotEqualsIgnoreSession(AutofillId id1, AutofillId id2) {
+ assertWithMessage("id1 is null").that(id1).isNotNull();
+ assertWithMessage("id2 is null").that(id2).isNotNull();
+ assertWithMessage("%s is not equal to %s", id1, id2).that(id1.equalsIgnoreSession(id2))
+ .isFalse();
+ }
+
+ private void assertNonVirtual(AutofillId id, int expectedId, int expectSessionId) {
+ assertThat(id.getViewId()).isEqualTo(expectedId);
+ assertThat(id.isNonVirtual()).isTrue();
+ assertThat(id.isVirtualInt()).isFalse();
+ assertThat(id.isVirtualLong()).isFalse();
+ assertThat(id.getVirtualChildIntId()).isEqualTo(View.NO_ID);
+ assertThat(id.getVirtualChildLongId()).isEqualTo(View.NO_ID);
+ assertThat(id.getSessionId()).isEqualTo(expectSessionId);
+ }
}
diff --git a/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java
index ace6611..833530d 100644
--- a/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java
@@ -16,19 +16,9 @@
package android.view.inputmethod;
-import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
-import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
-import static android.view.inputmethod.CursorAnchorInfo.FLAG_IS_RTL;
-
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
import android.graphics.Matrix;
-import android.graphics.RectF;
-import android.os.Parcel;
-import android.text.TextUtils;
import android.view.inputmethod.CursorAnchorInfo.Builder;
import androidx.test.filters.SmallTest;
@@ -37,437 +27,38 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.Objects;
-
@SmallTest
@RunWith(AndroidJUnit4.class)
public class CursorAnchorInfoTest {
- private static final float EPSILON = 0.0000001f;
-
- private static final RectF[] MANY_BOUNDS = new RectF[] {
- new RectF(101.0f, 201.0f, 301.0f, 401.0f),
- new RectF(102.0f, 202.0f, 302.0f, 402.0f),
- new RectF(103.0f, 203.0f, 303.0f, 403.0f),
- new RectF(104.0f, 204.0f, 304.0f, 404.0f),
- new RectF(105.0f, 205.0f, 305.0f, 405.0f),
- new RectF(106.0f, 206.0f, 306.0f, 406.0f),
- new RectF(107.0f, 207.0f, 307.0f, 407.0f),
- new RectF(108.0f, 208.0f, 308.0f, 408.0f),
- new RectF(109.0f, 209.0f, 309.0f, 409.0f),
- new RectF(110.0f, 210.0f, 310.0f, 410.0f),
- new RectF(111.0f, 211.0f, 311.0f, 411.0f),
- new RectF(112.0f, 212.0f, 312.0f, 412.0f),
- new RectF(113.0f, 213.0f, 313.0f, 413.0f),
- new RectF(114.0f, 214.0f, 314.0f, 414.0f),
- new RectF(115.0f, 215.0f, 315.0f, 415.0f),
- new RectF(116.0f, 216.0f, 316.0f, 416.0f),
- new RectF(117.0f, 217.0f, 317.0f, 417.0f),
- new RectF(118.0f, 218.0f, 318.0f, 418.0f),
- new RectF(119.0f, 219.0f, 319.0f, 419.0f),
- };
- private static final int[] MANY_FLAGS_ARRAY = new int[] {
- FLAG_HAS_INVISIBLE_REGION,
- FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION,
- FLAG_HAS_VISIBLE_REGION,
- FLAG_HAS_VISIBLE_REGION,
- FLAG_HAS_VISIBLE_REGION,
- FLAG_HAS_VISIBLE_REGION,
- FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
- FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
- FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL,
- FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
- FLAG_HAS_VISIBLE_REGION,
- FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
- FLAG_HAS_VISIBLE_REGION,
- FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
- FLAG_HAS_VISIBLE_REGION,
- FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
- FLAG_HAS_VISIBLE_REGION,
- FLAG_HAS_INVISIBLE_REGION,
- FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL,
- };
-
@Test
- public void testBuilder() throws Exception {
- final int SELECTION_START = 30;
- final int SELECTION_END = 40;
- final int COMPOSING_TEXT_START = 32;
- final String COMPOSING_TEXT = "test";
- final int INSERTION_MARKER_FLAGS =
- FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL;
- final float INSERTION_MARKER_HORIZONTAL = 10.5f;
- final float INSERTION_MARKER_TOP = 100.1f;
- final float INSERTION_MARKER_BASELINE = 110.4f;
- final float INSERTION_MARKER_BOTOM = 111.0f;
-
- Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX);
- TRANSFORM_MATRIX.setScale(10.0f, 20.0f);
-
+ public void testCreateForAdditionalParentMatrix() {
+ final Matrix originalMatrix = new Matrix();
+ originalMatrix.setTranslate(10.0f, 20.0f);
final Builder builder = new Builder();
- builder.setSelectionRange(SELECTION_START, SELECTION_END)
- .setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT)
- .setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
- INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS)
- .setMatrix(TRANSFORM_MATRIX);
- for (int i = 0; i < MANY_BOUNDS.length; i++) {
- final RectF bounds = MANY_BOUNDS[i];
- final int flags = MANY_FLAGS_ARRAY[i];
- builder.addCharacterBounds(i, bounds.left, bounds.top, bounds.right, bounds.bottom,
- flags);
- }
+ builder.setMatrix(originalMatrix);
- final CursorAnchorInfo info = builder.build();
- assertEquals(SELECTION_START, info.getSelectionStart());
- assertEquals(SELECTION_END, info.getSelectionEnd());
- assertEquals(COMPOSING_TEXT_START, info.getComposingTextStart());
- assertTrue(TextUtils.equals(COMPOSING_TEXT, info.getComposingText()));
- assertEquals(INSERTION_MARKER_FLAGS, info.getInsertionMarkerFlags());
- assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal(), EPSILON);
- assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop(), EPSILON);
- assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline(), EPSILON);
- assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom(), EPSILON);
- assertEquals(TRANSFORM_MATRIX, info.getMatrix());
- for (int i = 0; i < MANY_BOUNDS.length; i++) {
- final RectF expectedBounds = MANY_BOUNDS[i];
- assertEquals(expectedBounds, info.getCharacterBounds(i));
- }
- assertNull(info.getCharacterBounds(-1));
- assertNull(info.getCharacterBounds(MANY_BOUNDS.length + 1));
- for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
- final int expectedFlags = MANY_FLAGS_ARRAY[i];
- assertEquals(expectedFlags, info.getCharacterBoundsFlags(i));
- }
- assertEquals(0, info.getCharacterBoundsFlags(-1));
- assertEquals(0, info.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
+ final CursorAnchorInfo originalInstance = builder.build();
- // Make sure that the builder can reproduce the same object.
- final CursorAnchorInfo info2 = builder.build();
- assertEquals(SELECTION_START, info2.getSelectionStart());
- assertEquals(SELECTION_END, info2.getSelectionEnd());
- assertEquals(COMPOSING_TEXT_START, info2.getComposingTextStart());
- assertTrue(TextUtils.equals(COMPOSING_TEXT, info2.getComposingText()));
- assertEquals(INSERTION_MARKER_FLAGS, info2.getInsertionMarkerFlags());
- assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal(), EPSILON);
- assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop(), EPSILON);
- assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline(), EPSILON);
- assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom(), EPSILON);
- assertEquals(TRANSFORM_MATRIX, info2.getMatrix());
- for (int i = 0; i < MANY_BOUNDS.length; i++) {
- final RectF expectedBounds = MANY_BOUNDS[i];
- assertEquals(expectedBounds, info2.getCharacterBounds(i));
- }
- assertNull(info2.getCharacterBounds(-1));
- assertNull(info2.getCharacterBounds(MANY_BOUNDS.length + 1));
- for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
- final int expectedFlags = MANY_FLAGS_ARRAY[i];
- assertEquals(expectedFlags, info2.getCharacterBoundsFlags(i));
- }
- assertEquals(0, info2.getCharacterBoundsFlags(-1));
- assertEquals(0, info2.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
- assertEquals(info, info2);
- assertEquals(info.hashCode(), info2.hashCode());
+ assertEquals(originalMatrix, originalInstance.getMatrix());
- // Make sure that object can be marshaled via {@link Parsel}.
- final CursorAnchorInfo info3 = cloneViaParcel(info2);
- assertEquals(SELECTION_START, info3.getSelectionStart());
- assertEquals(SELECTION_END, info3.getSelectionEnd());
- assertEquals(COMPOSING_TEXT_START, info3.getComposingTextStart());
- assertTrue(TextUtils.equals(COMPOSING_TEXT, info3.getComposingText()));
- assertEquals(INSERTION_MARKER_FLAGS, info3.getInsertionMarkerFlags());
- assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal(), EPSILON);
- assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop(), EPSILON);
- assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline(), EPSILON);
- assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom(), EPSILON);
- assertEquals(TRANSFORM_MATRIX, info3.getMatrix());
- for (int i = 0; i < MANY_BOUNDS.length; i++) {
- final RectF expectedBounds = MANY_BOUNDS[i];
- assertEquals(expectedBounds, info3.getCharacterBounds(i));
- }
- assertNull(info3.getCharacterBounds(-1));
- assertNull(info3.getCharacterBounds(MANY_BOUNDS.length + 1));
- for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
- final int expectedFlags = MANY_FLAGS_ARRAY[i];
- assertEquals(expectedFlags, info3.getCharacterBoundsFlags(i));
- }
- assertEquals(0, info3.getCharacterBoundsFlags(-1));
- assertEquals(0, info3.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
- assertEquals(info.hashCode(), info3.hashCode());
+ final Matrix additionalParentMatrix = new Matrix();
+ additionalParentMatrix.setTranslate(1.0f, 2.0f);
+
+ final Matrix newMatrix = new Matrix(originalMatrix);
+ newMatrix.postConcat(additionalParentMatrix);
builder.reset();
- final CursorAnchorInfo uninitializedInfo = builder.build();
- assertEquals(-1, uninitializedInfo.getSelectionStart());
- assertEquals(-1, uninitializedInfo.getSelectionEnd());
- assertEquals(-1, uninitializedInfo.getComposingTextStart());
- assertNull(uninitializedInfo.getComposingText());
- assertEquals(0, uninitializedInfo.getInsertionMarkerFlags());
- assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal(), EPSILON);
- assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop(), EPSILON);
- assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline(), EPSILON);
- assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBottom(), EPSILON);
- assertEquals(Matrix.IDENTITY_MATRIX, uninitializedInfo.getMatrix());
- }
+ builder.setMatrix(newMatrix);
+ // An instance created by the standard Builder class.
+ final CursorAnchorInfo newInstanceByBuilder = builder.build();
- private static void assertNotEquals(final CursorAnchorInfo reference,
- final CursorAnchorInfo actual) {
- assertFalse(Objects.equals(reference, actual));
- }
+ // An instance created by an @hide method.
+ final CursorAnchorInfo newInstanceByMethod =
+ CursorAnchorInfo.createForAdditionalParentMatrix(
+ originalInstance, additionalParentMatrix);
- @Test
- public void testEquality() throws Exception {
- final Matrix MATRIX1 = new Matrix();
- MATRIX1.setTranslate(10.0f, 20.0f);
- final Matrix MATRIX2 = new Matrix();
- MATRIX2.setTranslate(110.0f, 120.0f);
- final Matrix NAN_MATRIX = new Matrix();
- NAN_MATRIX.setValues(new float[]{
- Float.NaN, Float.NaN, Float.NaN,
- Float.NaN, Float.NaN, Float.NaN,
- Float.NaN, Float.NaN, Float.NaN});
- final int SELECTION_START1 = 2;
- final int SELECTION_END1 = 7;
- final String COMPOSING_TEXT1 = "0123456789";
- final int COMPOSING_TEXT_START1 = 0;
- final int INSERTION_MARKER_FLAGS1 = FLAG_HAS_VISIBLE_REGION;
- final float INSERTION_MARKER_HORIZONTAL1 = 10.5f;
- final float INSERTION_MARKER_TOP1 = 100.1f;
- final float INSERTION_MARKER_BASELINE1 = 110.4f;
- final float INSERTION_MARKER_BOTOM1 = 111.0f;
- final int SELECTION_START2 = 4;
- final int SELECTION_END2 = 8;
- final String COMPOSING_TEXT2 = "9876543210";
- final int COMPOSING_TEXT_START2 = 3;
- final int INSERTION_MARKER_FLAGS2 =
- FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL;
- final float INSERTION_MARKER_HORIZONTAL2 = 14.5f;
- final float INSERTION_MARKER_TOP2 = 200.1f;
- final float INSERTION_MARKER_BASELINE2 = 210.4f;
- final float INSERTION_MARKER_BOTOM2 = 211.0f;
-
- // Default instance should be equal.
- assertEquals(new Builder().build(), new Builder().build());
-
- assertEquals(
- new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
- new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build());
- assertNotEquals(
- new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
- new Builder().setSelectionRange(SELECTION_START1, SELECTION_END2).build());
- assertNotEquals(
- new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
- new Builder().setSelectionRange(SELECTION_START2, SELECTION_END1).build());
- assertNotEquals(
- new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
- new Builder().setSelectionRange(SELECTION_START2, SELECTION_END2).build());
- assertEquals(
- new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
- new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build());
- assertNotEquals(
- new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
- new Builder().setComposingText(COMPOSING_TEXT_START2, COMPOSING_TEXT1).build());
- assertNotEquals(
- new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
- new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT2).build());
- assertNotEquals(
- new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
- new Builder().setComposingText(COMPOSING_TEXT_START2, COMPOSING_TEXT2).build());
-
- // For insertion marker locations, {@link Float#NaN} is treated as if it was a number.
- assertEquals(
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- Float.NaN, Float.NaN, Float.NaN, Float.NaN,
- INSERTION_MARKER_FLAGS1).build(),
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- Float.NaN, Float.NaN, Float.NaN, Float.NaN,
- INSERTION_MARKER_FLAGS1).build());
-
- // Check Matrix.
- assertEquals(
- new Builder().setMatrix(MATRIX1).build(),
- new Builder().setMatrix(MATRIX1).build());
- assertNotEquals(
- new Builder().setMatrix(MATRIX1).build(),
- new Builder().setMatrix(MATRIX2).build());
- assertNotEquals(
- new Builder().setMatrix(MATRIX1).build(),
- new Builder().setMatrix(NAN_MATRIX).build());
- // Unlike insertion marker locations, {@link Float#NaN} in the matrix is treated as just a
- // NaN as usual (NaN == NaN -> false).
- assertNotEquals(
- new Builder().setMatrix(NAN_MATRIX).build(),
- new Builder().setMatrix(NAN_MATRIX).build());
-
- assertEquals(
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build(),
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build());
- assertNotEquals(
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- Float.NaN, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build(),
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build());
- assertNotEquals(
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build(),
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build());
- assertNotEquals(
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build(),
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP2,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build());
- assertNotEquals(
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build(),
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE2, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build());
- assertNotEquals(
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build(),
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build());
- assertNotEquals(
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build(),
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM2,
- INSERTION_MARKER_FLAGS1).build());
- assertNotEquals(
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS1).build(),
- new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
- INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
- INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_FLAGS2).build());
- }
-
- @Test
- public void testMatrixIsCopied() throws Exception {
- final Matrix MATRIX1 = new Matrix();
- MATRIX1.setTranslate(10.0f, 20.0f);
- final Matrix MATRIX2 = new Matrix();
- MATRIX2.setTranslate(110.0f, 120.0f);
- final Matrix MATRIX3 = new Matrix();
- MATRIX3.setTranslate(210.0f, 220.0f);
- final Matrix matrix = new Matrix();
- final Builder builder = new Builder();
-
- matrix.set(MATRIX1);
- builder.setMatrix(matrix);
- matrix.postRotate(90.0f);
-
- final CursorAnchorInfo firstInstance = builder.build();
- assertEquals(MATRIX1, firstInstance.getMatrix());
- matrix.set(MATRIX2);
- builder.setMatrix(matrix);
- final CursorAnchorInfo secondInstance = builder.build();
- assertEquals(MATRIX1, firstInstance.getMatrix());
- assertEquals(MATRIX2, secondInstance.getMatrix());
-
- matrix.set(MATRIX3);
- assertEquals(MATRIX1, firstInstance.getMatrix());
- assertEquals(MATRIX2, secondInstance.getMatrix());
- }
-
- @Test
- public void testMatrixIsRequired() throws Exception {
- final int SELECTION_START = 30;
- final int SELECTION_END = 40;
- final int COMPOSING_TEXT_START = 32;
- final String COMPOSING_TEXT = "test";
- final int INSERTION_MARKER_FLAGS = FLAG_HAS_VISIBLE_REGION;
- final float INSERTION_MARKER_HORIZONTAL = 10.5f;
- final float INSERTION_MARKER_TOP = 100.1f;
- final float INSERTION_MARKER_BASELINE = 110.4f;
- final float INSERTION_MARKER_BOTOM = 111.0f;
- Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX);
- TRANSFORM_MATRIX.setScale(10.0f, 20.0f);
-
- final Builder builder = new Builder();
- // Check twice to make sure if Builder#reset() works as expected.
- for (int repeatCount = 0; repeatCount < 2; ++repeatCount) {
- builder.setSelectionRange(SELECTION_START, SELECTION_END)
- .setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT);
- try {
- // Should succeed as coordinate transformation matrix is not required if no
- // positional information is specified.
- builder.build();
- } catch (IllegalArgumentException ex) {
- assertTrue(false);
- }
-
- builder.setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
- INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS);
- try {
- // Coordinate transformation matrix is required if no positional information is
- // specified.
- builder.build();
- assertTrue(false);
- } catch (IllegalArgumentException ex) {
- }
-
- builder.setMatrix(TRANSFORM_MATRIX);
- try {
- // Should succeed as coordinate transformation matrix is required.
- builder.build();
- } catch (IllegalArgumentException ex) {
- assertTrue(false);
- }
-
- builder.reset();
- }
- }
-
- @Test
- public void testBuilderAddCharacterBounds() throws Exception {
- // A negative index should be rejected.
- try {
- new Builder().addCharacterBounds(-1, 0.0f, 0.0f, 0.0f, 0.0f, FLAG_HAS_VISIBLE_REGION);
- assertTrue(false);
- } catch (IllegalArgumentException ex) {
- }
- }
-
- private static CursorAnchorInfo cloneViaParcel(final CursorAnchorInfo src) {
- Parcel parcel = null;
- try {
- parcel = Parcel.obtain();
- src.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- return new CursorAnchorInfo(parcel);
- } finally {
- if (parcel != null) {
- parcel.recycle();
- }
- }
+ assertEquals(newMatrix, newInstanceByBuilder.getMatrix());
+ assertEquals(newMatrix, newInstanceByMethod.getMatrix());
+ assertEquals(newInstanceByBuilder.hashCode(), newInstanceByMethod.hashCode());
}
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/ConfigParserTest.java b/core/tests/coretests/src/android/view/textclassifier/ConfigParserTest.java
index f1cfe24..d54ce51 100644
--- a/core/tests/coretests/src/android/view/textclassifier/ConfigParserTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/ConfigParserTest.java
@@ -26,16 +26,17 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
+import java.util.function.Supplier;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ConfigParserTest {
- private static final String SETTINGS = "int=42,float=12.3,boolean=true,string=abc";
+ private static final Supplier<String> SETTINGS =
+ () -> "int=42,float=12.3,boolean=true,string=abc";
private static final String CLEAR_DEVICE_CONFIG_KEY_CMD =
"device_config delete " + DeviceConfig.NAMESPACE_TEXTCLASSIFIER;
private static final String[] DEVICE_CONFIG_KEYS = new String[]{
@@ -59,7 +60,6 @@
}
@Test
- @Ignore // TODO: Re-enable once ConfigParser#ENABLE_DEVICE_CONFIG is finalized
public void getBoolean_deviceConfig() {
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
@@ -79,7 +79,6 @@
}
@Test
- @Ignore // TODO: Re-enable once ConfigParser#ENABLE_DEVICE_CONFIG is finalized
public void getInt_deviceConfig() {
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
@@ -97,7 +96,6 @@
}
@Test
- @Ignore // TODO: Re-enable once ConfigParser#ENABLE_DEVICE_CONFIG is finalized
public void getFloat_deviceConfig() {
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
@@ -115,7 +113,6 @@
}
@Test
- @Ignore // TODO: Re-enable once ConfigParser#ENABLE_DEVICE_CONFIG is finalized
public void getString_deviceConfig() {
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
index f6bb1bf..789b829 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
@@ -50,9 +50,11 @@
+ "in_app_conversation_action_types_default=text_reply,"
+ "notification_conversation_action_types_default=send_email:call_phone,"
+ "lang_id_threshold_override=0.3,"
- + "lang_id_context_settings=10:1:0.5";
- final TextClassificationConstants constants =
- TextClassificationConstants.loadFromString(s);
+ + "lang_id_context_settings=10:1:0.5,"
+ + "detect_language_from_text_enabled=true,"
+ + "template_intent_factory_enabled=true,"
+ + "translate_in_classification_enabled=true";
+ final TextClassificationConstants constants = new TextClassificationConstants(() -> s);
assertWithMessage("local_textclassifier_enabled")
.that(constants.isLocalTextClassifierEnabled()).isTrue();
@@ -95,6 +97,12 @@
.that(constants.getLangIdThresholdOverride()).isWithin(EPSILON).of(0.3f);
Assert.assertArrayEquals("lang_id_context_settings",
constants.getLangIdContextSettings(), new float[]{10, 1, 0.5f}, EPSILON);
+ assertWithMessage("detect_language_from_text_enabled")
+ .that(constants.isLocalTextClassifierEnabled()).isTrue();
+ assertWithMessage("template_intent_factory_enabled")
+ .that(constants.isLocalTextClassifierEnabled()).isTrue();
+ assertWithMessage("translate_in_classification_enabled")
+ .that(constants.isLocalTextClassifierEnabled()).isTrue();
}
@Test
@@ -116,9 +124,11 @@
+ "in_app_conversation_action_types_default=view_map:track_flight,"
+ "notification_conversation_action_types_default=share_location,"
+ "lang_id_threshold_override=2,"
- + "lang_id_context_settings=30:0.5:0.3";
- final TextClassificationConstants constants =
- TextClassificationConstants.loadFromString(s);
+ + "lang_id_context_settings=30:0.5:0.3,"
+ + "detect_language_from_text_enabled=false,"
+ + "template_intent_factory_enabled=false,"
+ + "translate_in_classification_enabled=false";
+ final TextClassificationConstants constants = new TextClassificationConstants(() -> s);
assertWithMessage("local_textclassifier_enabled")
.that(constants.isLocalTextClassifierEnabled()).isFalse();
@@ -161,12 +171,17 @@
.that(constants.getLangIdThresholdOverride()).isWithin(EPSILON).of(2f);
Assert.assertArrayEquals("lang_id_context_settings",
constants.getLangIdContextSettings(), new float[]{30, 0.5f, 0.3f}, EPSILON);
+ assertWithMessage("detect_language_from_text_enabled")
+ .that(constants.isLocalTextClassifierEnabled()).isFalse();
+ assertWithMessage("template_intent_factory_enabled")
+ .that(constants.isLocalTextClassifierEnabled()).isFalse();
+ assertWithMessage("translate_in_classification_enabled")
+ .that(constants.isLocalTextClassifierEnabled()).isFalse();
}
@Test
public void testLoadFromString_defaultValues() {
- final TextClassificationConstants constants =
- TextClassificationConstants.loadFromString("");
+ final TextClassificationConstants constants = new TextClassificationConstants(() -> "");
assertWithMessage("local_textclassifier_enabled")
.that(constants.isLocalTextClassifierEnabled()).isTrue();
@@ -213,5 +228,11 @@
.that(constants.getLangIdThresholdOverride()).isWithin(EPSILON).of(-1f);
Assert.assertArrayEquals("lang_id_context_settings",
constants.getLangIdContextSettings(), new float[]{20, 1, 0.4f}, EPSILON);
+ assertWithMessage("detect_language_from_text_enabled")
+ .that(constants.isLocalTextClassifierEnabled()).isTrue();
+ assertWithMessage("template_intent_factory_enabled")
+ .that(constants.isLocalTextClassifierEnabled()).isTrue();
+ assertWithMessage("translate_in_classification_enabled")
+ .that(constants.isLocalTextClassifierEnabled()).isTrue();
}
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index 4fcd51c..9148185 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -77,7 +77,7 @@
TextClassifier fallback = TextClassifier.NO_OP;
TextClassifier classifier = new TextClassifierImpl(
- fakeContext, TextClassificationConstants.loadFromString(null), fallback);
+ fakeContext, new TextClassificationConstants(() -> null), fallback);
String text = "Contact me at +12122537077";
String classifiedText = "+12122537077";
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
index aeb8949..c2fa8b2b 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
@@ -40,6 +40,7 @@
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -59,7 +60,7 @@
// TODO: Implement TextClassifierService testing.
private static final TextClassificationConstants TC_CONSTANTS =
- TextClassificationConstants.loadFromString("");
+ new TextClassificationConstants(() -> "");
private static final LocaleList LOCALES = LocaleList.forLanguageTags("en-US");
private static final String NO_TYPE = null;
@@ -411,6 +412,7 @@
assertThat(textLanguage, isTextLanguage("ja"));
}
+ @Ignore // Doesn't work without a language-based model.
@Test
public void testSuggestConversationActions_textReplyOnly_maxOne() {
if (isTextClassifierDisabled()) return;
@@ -438,6 +440,7 @@
Truth.assertThat(conversationAction.getTextReply()).isNotNull();
}
+ @Ignore // Doesn't work without a language-based model.
@Test
public void testSuggestConversationActions_textReplyOnly_noMax() {
if (isTextClassifierDisabled()) return;
@@ -493,6 +496,7 @@
Truth.assertThat(actionIntent.getData()).isEqualTo(Uri.parse("https://www.android.com"));
}
+ @Ignore // Doesn't work without a language-based model.
@Test
public void testSuggestConversationActions_copy() {
if (isTextClassifierDisabled()) return;
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/LocalOverlayManager.java b/core/tests/overlaytests/device/src/com/android/overlaytest/LocalOverlayManager.java
new file mode 100644
index 0000000..390bb76
--- /dev/null
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/LocalOverlayManager.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.overlaytest;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import android.app.UiAutomation;
+import android.content.res.Resources;
+import android.os.ParcelFileDescriptor;
+
+import androidx.test.InstrumentationRegistry;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.concurrent.Executor;
+import java.util.concurrent.FutureTask;
+
+class LocalOverlayManager {
+ private static final long TIMEOUT = 30;
+
+ public static void setEnabledAndWait(Executor executor, final String packageName,
+ boolean enable) throws Exception {
+ final String pattern = (enable ? "[x]" : "[ ]") + " " + packageName;
+ if (executeShellCommand("cmd overlay list").contains(pattern)) {
+ // nothing to do, overlay already in the requested state
+ return;
+ }
+
+ final Resources res = InstrumentationRegistry.getContext().getResources();
+ final String[] oldApkPaths = res.getAssets().getApkPaths();
+ FutureTask<Boolean> task = new FutureTask<>(() -> {
+ while (true) {
+ if (!Arrays.equals(oldApkPaths, res.getAssets().getApkPaths())) {
+ return true;
+ }
+ Thread.sleep(10);
+ }
+ });
+ executor.execute(task);
+ executeShellCommand("cmd overlay " + (enable ? "enable " : "disable ") + packageName);
+ task.get(TIMEOUT, SECONDS);
+ }
+
+ private static String executeShellCommand(final String command)
+ throws Exception {
+ final UiAutomation uiAutomation =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ final ParcelFileDescriptor pfd = uiAutomation.executeShellCommand(command);
+ try (InputStream in = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
+ final BufferedReader reader = new BufferedReader(
+ new InputStreamReader(in, StandardCharsets.UTF_8));
+ StringBuilder str = new StringBuilder();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ str.append(line);
+ }
+ return str.toString();
+ }
+ }
+}
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
index f86743a..fdb6bbb 100644
--- a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
@@ -21,13 +21,11 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.app.UiAutomation;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.LocaleList;
-import android.os.ParcelFileDescriptor;
import android.util.AttributeSet;
import android.util.Xml;
@@ -569,60 +567,4 @@
setLocale(new Locale("sv", "SE"));
assertResource(resId, 200, 400, 600);
}
-
- /**
- * Executes the shell command and reads all the output to ensure the command ran and didn't
- * get stuck buffering on output.
- */
- protected static String executeShellCommand(UiAutomation automation, String command)
- throws Exception {
- final ParcelFileDescriptor pfd = automation.executeShellCommand(command);
- try (InputStream in = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
- final BufferedReader reader = new BufferedReader(
- new InputStreamReader(in, StandardCharsets.UTF_8));
- StringBuilder str = new StringBuilder();
- String line;
- while ((line = reader.readLine()) != null) {
- str.append(line);
- }
- return str.toString();
- }
- }
-
- /**
- * Enables overlay packages and waits for a configuration change event before
- * returning, to guarantee that Resources are up-to-date.
- * @param packages the list of package names to enable.
- */
- protected static void enableOverlayPackages(String... packages) throws Exception {
- enableOverlayPackages(true, packages);
- }
-
- /**
- * Disables overlay packages and waits for a configuration change event before
- * returning, to guarantee that Resources are up-to-date.
- * @param packages the list of package names to disable.
- */
- protected static void disableOverlayPackages(String... packages) throws Exception {
- enableOverlayPackages(false, packages);
- }
-
- /**
- * Enables/disables overlay packages and waits for a configuration change event before
- * returning, to guarantee that Resources are up-to-date.
- * @param enable enables the overlays when true, disables when false.
- * @param packages the list of package names to enable/disable.
- */
- private static void enableOverlayPackages(boolean enable, String[] packages)
- throws Exception {
- final UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation()
- .getUiAutomation();
- for (final String pkg : packages) {
- executeShellCommand(uiAutomation,
- "cmd overlay " + (enable ? "enable " : "disable ") + pkg);
- }
-
- // Wait for the overlay change to propagate.
- Thread.sleep(1000);
- }
}
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/WithMultipleOverlaysTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/WithMultipleOverlaysTest.java
index cd3ed9d..d28c47d 100644
--- a/core/tests/overlaytests/device/src/com/android/overlaytest/WithMultipleOverlaysTest.java
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/WithMultipleOverlaysTest.java
@@ -22,6 +22,8 @@
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.concurrent.Executor;
+
@RunWith(JUnit4.class)
@MediumTest
public class WithMultipleOverlaysTest extends OverlayBaseTest {
@@ -31,6 +33,9 @@
@BeforeClass
public static void enableOverlay() throws Exception {
- enableOverlayPackages(APP_OVERLAY_ONE_PKG, APP_OVERLAY_TWO_PKG, FRAMEWORK_OVERLAY_PKG);
+ Executor executor = (cmd) -> new Thread(cmd).start();
+ LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_ONE_PKG, true);
+ LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_TWO_PKG, true);
+ LocalOverlayManager.setEnabledAndWait(executor, FRAMEWORK_OVERLAY_PKG, true);
}
}
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/WithOverlayTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/WithOverlayTest.java
index c0d4281..6566ad3 100644
--- a/core/tests/overlaytests/device/src/com/android/overlaytest/WithOverlayTest.java
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/WithOverlayTest.java
@@ -22,6 +22,8 @@
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.concurrent.Executor;
+
@RunWith(JUnit4.class)
@MediumTest
public class WithOverlayTest extends OverlayBaseTest {
@@ -31,7 +33,9 @@
@BeforeClass
public static void enableOverlay() throws Exception {
- disableOverlayPackages(APP_OVERLAY_TWO_PKG);
- enableOverlayPackages(APP_OVERLAY_ONE_PKG, FRAMEWORK_OVERLAY_PKG);
+ Executor executor = (cmd) -> new Thread(cmd).start();
+ LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_ONE_PKG, true);
+ LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_TWO_PKG, false);
+ LocalOverlayManager.setEnabledAndWait(executor, FRAMEWORK_OVERLAY_PKG, true);
}
}
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/WithoutOverlayTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/WithoutOverlayTest.java
index 33c7b25..48cfeab 100644
--- a/core/tests/overlaytests/device/src/com/android/overlaytest/WithoutOverlayTest.java
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/WithoutOverlayTest.java
@@ -22,6 +22,8 @@
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.concurrent.Executor;
+
@RunWith(JUnit4.class)
@MediumTest
public class WithoutOverlayTest extends OverlayBaseTest {
@@ -31,6 +33,9 @@
@BeforeClass
public static void disableOverlays() throws Exception {
- disableOverlayPackages(APP_OVERLAY_ONE_PKG, APP_OVERLAY_TWO_PKG, FRAMEWORK_OVERLAY_PKG);
+ Executor executor = (cmd) -> new Thread(cmd).start();
+ LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_ONE_PKG, false);
+ LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_TWO_PKG, false);
+ LocalOverlayManager.setEnabledAndWait(executor, FRAMEWORK_OVERLAY_PKG, false);
}
}
diff --git a/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java b/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java
index 267cb36..eec7be2 100644
--- a/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java
+++ b/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java
@@ -177,6 +177,23 @@
.contains(APP_OVERLAY_PACKAGE_NAME));
}
+ @Test
+ public void testAdbShellOMSInterface() throws Exception {
+ installPackage("OverlayHostTests_AppOverlayV1.apk");
+ assertTrue(shell("cmd overlay list " + DEVICE_TEST_PKG).contains(DEVICE_TEST_PKG));
+ assertTrue(shell("cmd overlay list " + DEVICE_TEST_PKG).contains(APP_OVERLAY_PACKAGE_NAME));
+ assertEquals("[ ] " + APP_OVERLAY_PACKAGE_NAME,
+ shell("cmd overlay list " + APP_OVERLAY_PACKAGE_NAME).trim());
+ assertEquals("STATE_DISABLED",
+ shell("cmd overlay dump state " + APP_OVERLAY_PACKAGE_NAME).trim());
+
+ setOverlayEnabled(APP_OVERLAY_PACKAGE_NAME, true);
+ assertEquals("[x] " + APP_OVERLAY_PACKAGE_NAME,
+ shell("cmd overlay list " + APP_OVERLAY_PACKAGE_NAME).trim());
+ assertEquals("STATE_ENABLED",
+ shell("cmd overlay dump state " + APP_OVERLAY_PACKAGE_NAME).trim());
+ }
+
private void delay() {
try {
Thread.sleep(1000);
@@ -195,20 +212,24 @@
}
private void installConvertExistingInstantPackageToFull(String pkg) throws Exception {
- getDevice().executeShellCommand("cmd package install-existing --wait --full " + pkg);
+ shell("cmd package install-existing --wait --full " + pkg);
}
private void setPackageEnabled(String pkg, boolean enabled) throws Exception {
- getDevice().executeShellCommand("cmd package " + (enabled ? "enable " : "disable ") + pkg);
+ shell("cmd package " + (enabled ? "enable " : "disable ") + pkg);
delay();
}
private void setOverlayEnabled(String pkg, boolean enabled) throws Exception {
- getDevice().executeShellCommand("cmd overlay " + (enabled ? "enable " : "disable ") + pkg);
+ shell("cmd overlay " + (enabled ? "enable " : "disable ") + pkg);
delay();
}
private boolean overlayManagerContainsPackage(String pkg) throws Exception {
- return getDevice().executeShellCommand("cmd overlay list").contains(pkg);
+ return shell("cmd overlay list").contains(pkg);
+ }
+
+ private String shell(final String cmd) throws Exception {
+ return getDevice().executeShellCommand(cmd);
}
}
diff --git a/core/tests/utiltests/Android.mk b/core/tests/utiltests/Android.mk
index 343c07a..9ef73e9 100644
--- a/core/tests/utiltests/Android.mk
+++ b/core/tests/utiltests/Android.mk
@@ -18,6 +18,7 @@
androidx.test.rules \
frameworks-base-testutils \
mockito-target-minus-junit4 \
+ androidx.test.ext.junit
LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
diff --git a/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
index 4b14284..57ee2d5 100644
--- a/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
+++ b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
@@ -21,6 +21,36 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
+jint android_util_MemoryIntArrayTest_createAshmem(__attribute__((unused)) JNIEnv* env,
+ __attribute__((unused)) jobject clazz,
+ jstring name, jint size)
+{
+
+ if (name == NULL) {
+ return -1;
+ }
+
+ if (size < 0) {
+ return -1;
+ }
+
+ const char* nameStr = env->GetStringUTFChars(name, NULL);
+ const int ashmemSize = sizeof(std::atomic_int) * size;
+ int fd = ashmem_create_region(nameStr, ashmemSize);
+ env->ReleaseStringUTFChars(name, nameStr);
+
+ if (fd < 0) {
+ return -1;
+ }
+
+ int setProtResult = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
+ if (setProtResult < 0) {
+ return -1;
+ }
+
+ return fd;
+}
+
void android_util_MemoryIntArrayTest_setAshmemSize(__attribute__((unused)) JNIEnv* env,
__attribute__((unused)) jobject clazz, jint fd, jint size)
{
diff --git a/core/tests/utiltests/jni/registration.cpp b/core/tests/utiltests/jni/registration.cpp
index d4fc2fb..0c84d98 100644
--- a/core/tests/utiltests/jni/registration.cpp
+++ b/core/tests/utiltests/jni/registration.cpp
@@ -16,14 +16,25 @@
#include <jni.h>
+extern jint android_util_MemoryIntArrayTest_createAshmem(JNIEnv* env,
+ jobject clazz, jstring name, jint size);
extern void android_util_MemoryIntArrayTest_setAshmemSize(JNIEnv* env,
jobject clazz, jint fd, jint size);
extern "C" {
+ JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
+ JNIEnv * env, jobject obj, jstring name, jint size);
JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
JNIEnv * env, jobject obj, jint fd, jint size);
};
+JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
+ __attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
+ jstring name, jint size)
+{
+ return android_util_MemoryIntArrayTest_createAshmem(env, obj, name, size);
+}
+
JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
__attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
jint fd, jint size)
diff --git a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
index 2daefe7..1966e12 100644
--- a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
+++ b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
@@ -23,9 +23,8 @@
import static org.junit.Assert.fail;
import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import libcore.io.IoUtils;
@@ -36,6 +35,8 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
@RunWith(AndroidJUnit4.class)
public class MemoryIntArrayTest {
static {
@@ -255,11 +256,13 @@
// Create a MemoryIntArray to muck with
MemoryIntArray array = new MemoryIntArray(1);
- // Grab the internal ashmem fd.
- Field fdField = MemoryIntArray.class.getDeclaredField("mFd");
- fdField.setAccessible(true);
- int fd = ((ParcelFileDescriptor)fdField.get(array)).getFd();
- assertTrue("fd must be valid", fd != -1);
+ // Create the fd to stuff in the MemoryIntArray
+ final int fd = nativeCreateAshmem("foo", 1);
+
+ // Replace the fd with our ahsmem region
+ Field fdFiled = MemoryIntArray.class.getDeclaredField("mFd");
+ fdFiled.setAccessible(true);
+ fdFiled.set(array, fd);
CountDownLatch countDownLatch = new CountDownLatch(2);
@@ -294,9 +297,10 @@
}
if (!success) {
- fail("MemoryIntArray should catch ashmem size changing under it");
+ fail("MemoryIntArray should catch ahshmem size changing under it");
}
}
+ private native int nativeCreateAshmem(String name, int size);
private native void nativeSetAshmemSize(int fd, int size);
}
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
new file mode 100644
index 0000000..37020fc
--- /dev/null
+++ b/data/etc/car/Android.bp
@@ -0,0 +1,123 @@
+// Copyright (C} 2019 The Android Open 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.
+
+
+
+// Privapp permission whitelist files
+
+prebuilt_etc {
+ name: "privapp_whitelist_android.car.cluster.loggingrenderer",
+ sub_dir: "permissions",
+ src: "android.car.cluster.loggingrenderer.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_android.car.cluster.sample",
+ sub_dir: "permissions",
+ src: "android.car.cluster.sample.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_android.car.usb.handler",
+ sub_dir: "permissions",
+ src: "android.car.usb.handler.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.carlauncher",
+ sub_dir: "permissions",
+ src: "com.android.car.carlauncher.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.dialer",
+ sub_dir: "permissions",
+ src: "com.android.car.dialer.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.hvac",
+ sub_dir: "permissions",
+ src: "com.android.car.hvac.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.media",
+ sub_dir: "permissions",
+ src: "com.android.car.media.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.notification",
+ sub_dir: "permissions",
+ src: "com.android.car.notification.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.radio",
+ sub_dir: "permissions",
+ src: "com.android.car.radio.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.settings",
+ sub_dir: "permissions",
+ src: "com.android.car.settings.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.themeplayground",
+ sub_dir: "permissions",
+ src: "com.android.car.themeplayground.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.trust",
+ sub_dir: "permissions",
+ src: "com.android.car.trust.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car",
+ sub_dir: "permissions",
+ src: "com.android.car.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.google.android.car.kitchensink",
+ sub_dir: "permissions",
+ src: "com.google.android.car.kitchensink.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.developeroptions",
+ sub_dir: "permissions",
+ src: "com.android.car.developeroptions.xml",
+ filename_from_src: true,
+ product_specific: true,
+}
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/data/etc/car/android.car.cluster.loggingrenderer.xml
similarity index 68%
rename from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
rename to data/etc/car/android.car.cluster.loggingrenderer.xml
index 8b8258f..784e0e7 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/data/etc/car/android.car.cluster.loggingrenderer.xml
@@ -14,13 +14,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<permissions>
+ <privapp-permissions package="android.car.cluster.loggingrenderer">
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/data/etc/car/android.car.cluster.sample.xml
similarity index 62%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to data/etc/car/android.car.cluster.sample.xml
index 8b8258f..75c57b8 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/data/etc/car/android.car.cluster.sample.xml
@@ -14,13 +14,11 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<permissions>
+ <privapp-permissions package="android.car.cluster.sample">
+ <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/data/etc/car/android.car.usb.handler.xml
similarity index 68%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to data/etc/car/android.car.usb.handler.xml
index 8b8258f..c67847c 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/data/etc/car/android.car.usb.handler.xml
@@ -14,13 +14,9 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<permissions>
+ <privapp-permissions package="android.car.usb.handler">
+ <permission name="android.permission.MANAGE_USB"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/data/etc/car/com.android.car.carlauncher.xml
similarity index 63%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to data/etc/car/com.android.car.carlauncher.xml
index 8b8258f..8ec1cd4 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/data/etc/car/com.android.car.carlauncher.xml
@@ -14,13 +14,11 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<permissions>
+ <privapp-permissions package="com.android.car.carlauncher">
+ <permission name="android.permission.ACTIVITY_EMBEDDING"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
+ <permission name="android.permission.PACKAGE_USAGE_STATS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/car/com.android.car.developeroptions.xml b/data/etc/car/com.android.car.developeroptions.xml
new file mode 100644
index 0000000..76c8c62
--- /dev/null
+++ b/data/etc/car/com.android.car.developeroptions.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+<permissions>
+ <privapp-permissions package="com.android.car.developeroptions">
+ <permission name="android.permission.ACCESS_CHECKIN_PROPERTIES"/>
+ <permission name="android.permission.ACCESS_NOTIFICATIONS"/>
+ <permission name="android.permission.BACKUP"/>
+ <permission name="android.permission.BATTERY_STATS"/>
+ <permission name="android.permission.BLUETOOTH_PRIVILEGED"/>
+ <permission name="android.permission.CHANGE_APP_IDLE_STATE"/>
+ <permission name="android.permission.CHANGE_CONFIGURATION"/>
+ <permission name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS"/>
+ <permission name="android.permission.DELETE_PACKAGES"/>
+ <permission name="android.permission.FORCE_STOP_PACKAGES"/>
+ <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
+ <permission name="android.permission.MANAGE_DEBUGGING"/>
+ <permission name="android.permission.MANAGE_FINGERPRINT"/>
+ <permission name="android.permission.MANAGE_USB"/>
+ <permission name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.MASTER_CLEAR"/>
+ <permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
+ <permission name="android.permission.MOVE_PACKAGE"/>
+ <permission name="android.permission.OVERRIDE_WIFI_CONFIG"/>
+ <permission name="android.permission.PACKAGE_USAGE_STATS"/>
+ <permission name="android.permission.READ_SEARCH_INDEXABLES"/>
+ <permission name="android.permission.REBOOT"/>
+ <permission name="android.permission.SET_TIME"/>
+ <permission name="android.permission.STATUS_BAR"/>
+ <permission name="android.permission.TETHER_PRIVILEGED"/>
+ <permission name="android.permission.USE_RESERVED_DISK"/>
+ <permission name="android.permission.USER_ACTIVITY"/>
+ <permission name="android.permission.WRITE_APN_SETTINGS"/>
+ <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
+ <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/data/etc/car/com.android.car.dialer.xml
similarity index 68%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to data/etc/car/com.android.car.dialer.xml
index 8b8258f..d44f5a1 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/data/etc/car/com.android.car.dialer.xml
@@ -14,13 +14,9 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<permissions>
+ <privapp-permissions package="com.android.car.dialer">
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ </privapp-permissions>
+</permissions>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/data/etc/car/com.android.car.hvac.xml
similarity index 68%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to data/etc/car/com.android.car.hvac.xml
index 8b8258f..d3631e0 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/data/etc/car/com.android.car.hvac.xml
@@ -14,13 +14,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<permissions>
+ <privapp-permissions package="com.android.car.hvac">
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/data/etc/car/com.android.car.media.xml
similarity index 68%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to data/etc/car/com.android.car.media.xml
index 8b8258f..d17453d 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/data/etc/car/com.android.car.media.xml
@@ -14,13 +14,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<permissions>
+ <privapp-permissions package="com.android.car.media">
+ <permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
+ </privapp-permissions>
+</permissions>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/data/etc/car/com.android.car.notification.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to data/etc/car/com.android.car.notification.xml
index 8b8258f..8479512 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/data/etc/car/com.android.car.notification.xml
@@ -14,13 +14,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<permissions>
+ <privapp-permissions package="com.android.car.notification">
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ </privapp-permissions>
+</permissions>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/data/etc/car/com.android.car.radio.xml
similarity index 68%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to data/etc/car/com.android.car.radio.xml
index 8b8258f..d7853ab 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/data/etc/car/com.android.car.radio.xml
@@ -14,13 +14,9 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<permissions>
+ <privapp-permissions package="com.android.car.radio">
+ <permission name="android.permission.ACCESS_BROADCAST_RADIO"/>
+ <permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/car/com.android.car.settings.xml b/data/etc/car/com.android.car.settings.xml
new file mode 100644
index 0000000..5f7e1c1
--- /dev/null
+++ b/data/etc/car/com.android.car.settings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+<permissions>
+ <privapp-permissions package="com.android.car.settings">
+ <permission name="android.permission.ACCESS_CHECKIN_PROPERTIES"/>
+ <permission name="android.permission.ACCESS_NOTIFICATIONS"/>
+ <permission name="android.permission.BACKUP"/>
+ <permission name="android.permission.BATTERY_STATS"/>
+ <permission name="android.permission.BLUETOOTH_PRIVILEGED"/>
+ <permission name="android.permission.CHANGE_APP_IDLE_STATE"/>
+ <permission name="android.permission.CHANGE_CONFIGURATION"/>
+ <permission name="android.permission.DELETE_PACKAGES"/>
+ <permission name="android.permission.DELETE_CACHE_FILES"/>
+ <permission name="android.permission.DUMP"/>
+ <permission name="android.permission.FORCE_STOP_PACKAGES"/>
+ <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
+ <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
+ <permission name="android.permission.MANAGE_DEBUGGING"/>
+ <permission name="android.permission.MANAGE_DEVICE_ADMINS"/>
+ <permission name="android.permission.MANAGE_FINGERPRINT"/>
+ <permission name="android.permission.MANAGE_USB"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE" />
+ <permission name="android.permission.MASTER_CLEAR"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
+ <permission name="android.permission.MOVE_PACKAGE"/>
+ <permission name="android.permission.OVERRIDE_WIFI_CONFIG"/>
+ <permission name="android.permission.PACKAGE_USAGE_STATS"/>
+ <permission name="android.permission.READ_SEARCH_INDEXABLES"/>
+ <permission name="android.permission.REBOOT"/>
+ <permission name="android.permission.SET_TIME"/>
+ <permission name="android.permission.SET_TIME_ZONE"/>
+ <permission name="android.permission.STATUS_BAR"/>
+ <permission name="android.permission.TETHER_PRIVILEGED"/>
+ <permission name="android.permission.USE_RESERVED_DISK"/>
+ <permission name="android.permission.USER_ACTIVITY"/>
+ <permission name="android.permission.WRITE_APN_SETTINGS"/>
+ <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
+ <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ <permission name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
+ </privapp-permissions>
+</permissions>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/data/etc/car/com.android.car.themeplayground.xml
similarity index 68%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to data/etc/car/com.android.car.themeplayground.xml
index 8b8258f..cab4718 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/data/etc/car/com.android.car.themeplayground.xml
@@ -14,13 +14,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<permissions>
+ <privapp-permissions package="com.android.car.themeplayground">
+ <permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/car/com.android.car.trust.xml b/data/etc/car/com.android.car.trust.xml
new file mode 100644
index 0000000..dc87af2
--- /dev/null
+++ b/data/etc/car/com.android.car.trust.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+<permissions>
+ <privapp-permissions package="com.android.car.trust">
+ <permission name="android.permission.BLUETOOTH" />
+ <permission name="android.permission.BLUETOOTH_ADMIN" />
+ <permission name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <permission name="android.permission.ACCESS_FINE_LOCATION"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <permission name="android.permission.MANAGE_USERS" />
+ <permission name="android.permission.CONTROL_KEYGUARD" />
+ <permission name="android.permission.PROVIDE_TRUST_AGENT" />
+ <permission name="android.permission.RECEIVE_BOOT_COMPLETED" />
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/car/com.android.car.xml b/data/etc/car/com.android.car.xml
new file mode 100644
index 0000000..f1797de
--- /dev/null
+++ b/data/etc/car/com.android.car.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+<permissions>
+ <privapp-permissions package="com.android.car">
+ <permission name="android.permission.LOCATION_HARDWARE"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.MODIFY_AUDIO_ROUTING"/>
+ <permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ <permission name="android.permission.PROVIDE_TRUST_AGENT"/>
+ <permission name="android.permission.REAL_GET_TASKS"/>
+ <permission name="android.permission.REBOOT"/>
+ <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml
new file mode 100644
index 0000000..6b26e8f
--- /dev/null
+++ b/data/etc/car/com.google.android.car.kitchensink.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+<permissions>
+ <privapp-permissions package="com.google.android.car.kitchensink">
+ <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+ <permission name="android.permission.LOCATION_HARDWARE"/>
+ <permission name="android.permission.MANAGE_USB"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.MODIFY_AUDIO_ROUTING"/>
+ <permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ <permission name="android.permission.PROVIDE_TRUST_AGENT"/>
+ <permission name="android.permission.REAL_GET_TASKS"/>
+ <permission name="android.permission.REBOOT"/>
+ <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/com.android.dialer.xml b/data/etc/com.android.dialer.xml
index ccdb21f..405279f 100644
--- a/data/etc/com.android.dialer.xml
+++ b/data/etc/com.android.dialer.xml
@@ -24,5 +24,7 @@
<permission name="android.permission.STOP_APP_SWITCHES"/>
<permission name="com.android.voicemail.permission.READ_VOICEMAIL"/>
<permission name="com.android.voicemail.permission.WRITE_VOICEMAIL"/>
+ <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
</privapp-permissions>
</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 98ef00e..b96c59a 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -49,13 +49,6 @@
<permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
</privapp-permissions>
- <privapp-permissions package="com.android.defcontainer">
- <permission name="android.permission.ACCESS_CACHE_FILESYSTEM"/>
- <permission name="android.permission.ALLOCATE_AGGRESSIVE"/>
- <permission name="android.permission.INTERACT_ACROSS_USERS"/>
- <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
- </privapp-permissions>
-
<privapp-permissions package="com.android.externalstorage">
<permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<permission name="android.permission.WRITE_MEDIA_STORAGE"/>
@@ -83,6 +76,7 @@
<permission name="android.permission.SET_TIME_ZONE"/>
<permission name="android.permission.SHUTDOWN"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
</privapp-permissions>
<privapp-permissions package="com.android.mms.service">
@@ -303,6 +297,7 @@
<permission name="android.permission.SET_TIME"/>
<permission name="android.permission.SET_TIME_ZONE"/>
<permission name="android.permission.SIGNAL_PERSISTENT_PROCESSES"/>
+ <permission name="android.permission.STATUS_BAR"/>
<permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
<permission name="android.permission.START_TASKS_FROM_RECENTS" />
<permission name="android.permission.STOP_APP_SWITCHES"/>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 07f81c1..4471017 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -2197,8 +2197,12 @@
}
/**
- *
* @return {@link GraphicBuffer} which is internally used by hardware bitmap
+ *
+ * Note: the GraphicBuffer does *not* have an associated {@link ColorSpace}.
+ * To render this object the same as its rendered with this Bitmap, you
+ * should also call {@link getColorSpace}.
+ *
* @hide
*/
@UnsupportedAppUsage
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 11d635e..297153d 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -637,8 +637,7 @@
* @see #setOrientation(Orientation)
*/
public Orientation getOrientation() {
- updateGradientStateOrientation();
- return mGradientState.mOrientation;
+ return mGradientState.getOrientation();
}
/**
@@ -654,10 +653,7 @@
* @see #getOrientation()
*/
public void setOrientation(Orientation orientation) {
- // Update the angle here so that subsequent attempts to obtain the orientation
- // from the angle overwrite previously configured values during inflation
- mGradientState.mAngle = getAngleFromOrientation(orientation);
- mGradientState.mOrientation = orientation;
+ mGradientState.setOrientation(orientation);
mGradientIsDirty = true;
invalidateSelf();
}
@@ -1246,76 +1242,6 @@
}
/**
- * Update the orientation of the gradient based on the given angle only if the type is
- * {@link #LINEAR_GRADIENT}
- */
- private void updateGradientStateOrientation() {
- if (mGradientState.mGradient == LINEAR_GRADIENT) {
- int angle = mGradientState.mAngle;
- if (angle % 45 != 0) {
- throw new IllegalArgumentException("Linear gradient requires 'angle' attribute to "
- + "be a multiple of 45");
- }
-
- Orientation orientation;
- switch (angle) {
- case 0:
- orientation = Orientation.LEFT_RIGHT;
- break;
- case 45:
- orientation = Orientation.BL_TR;
- break;
- case 90:
- orientation = Orientation.BOTTOM_TOP;
- break;
- case 135:
- orientation = Orientation.BR_TL;
- break;
- case 180:
- orientation = Orientation.RIGHT_LEFT;
- break;
- case 225:
- orientation = Orientation.TR_BL;
- break;
- case 270:
- orientation = Orientation.TOP_BOTTOM;
- break;
- case 315:
- orientation = Orientation.TL_BR;
- break;
- default:
- // Should not get here as exception is thrown above if angle is not multiple
- // of 45 degrees
- orientation = Orientation.LEFT_RIGHT;
- break;
- }
- mGradientState.mOrientation = orientation;
- }
- }
-
- private int getAngleFromOrientation(Orientation orientation) {
- switch (orientation) {
- default:
- case LEFT_RIGHT:
- return 0;
- case BL_TR:
- return 45;
- case BOTTOM_TOP:
- return 90;
- case BR_TL:
- return 135;
- case RIGHT_LEFT:
- return 180;
- case TR_BL:
- return 225;
- case TOP_BOTTOM:
- return 270;
- case TL_BR:
- return 315;
- }
- }
-
- /**
* This checks mGradientIsDirty, and if it is true, recomputes both our drawing
* rectangle (mRect) and the gradient itself, since it depends on our
* rectangle too.
@@ -1344,8 +1270,7 @@
if (st.mGradient == LINEAR_GRADIENT) {
final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f;
- updateGradientStateOrientation();
- switch (st.mOrientation) {
+ switch (st.getOrientation()) {
case TOP_BOTTOM:
x0 = r.left; y0 = r.top;
x1 = x0; y1 = level * r.bottom;
@@ -2056,7 +1981,7 @@
int[] mAttrPadding;
public GradientState(Orientation orientation, int[] gradientColors) {
- mOrientation = orientation;
+ setOrientation(orientation);
setGradientColors(gradientColors);
}
@@ -2259,6 +2184,93 @@
mCenterY = y;
}
+ public void setOrientation(Orientation orientation) {
+ // Update the angle here so that subsequent attempts to obtain the orientation
+ // from the angle overwrite previously configured values during inflation
+ mAngle = getAngleFromOrientation(orientation);
+ mOrientation = orientation;
+ }
+
+ @NonNull
+ public Orientation getOrientation() {
+ updateGradientStateOrientation();
+ return mOrientation;
+ }
+
+ /**
+ * Update the orientation of the gradient based on the given angle only if the type is
+ * {@link #LINEAR_GRADIENT}
+ */
+ private void updateGradientStateOrientation() {
+ if (mGradient == LINEAR_GRADIENT) {
+ int angle = mAngle;
+ if (angle % 45 != 0) {
+ throw new IllegalArgumentException("Linear gradient requires 'angle' attribute "
+ + "to be a multiple of 45");
+ }
+
+ Orientation orientation;
+ switch (angle) {
+ case 0:
+ orientation = Orientation.LEFT_RIGHT;
+ break;
+ case 45:
+ orientation = Orientation.BL_TR;
+ break;
+ case 90:
+ orientation = Orientation.BOTTOM_TOP;
+ break;
+ case 135:
+ orientation = Orientation.BR_TL;
+ break;
+ case 180:
+ orientation = Orientation.RIGHT_LEFT;
+ break;
+ case 225:
+ orientation = Orientation.TR_BL;
+ break;
+ case 270:
+ orientation = Orientation.TOP_BOTTOM;
+ break;
+ case 315:
+ orientation = Orientation.TL_BR;
+ break;
+ default:
+ // Should not get here as exception is thrown above if angle is not multiple
+ // of 45 degrees
+ orientation = Orientation.LEFT_RIGHT;
+ break;
+ }
+ mOrientation = orientation;
+ }
+ }
+
+ private int getAngleFromOrientation(@Nullable Orientation orientation) {
+ if (orientation != null) {
+ switch (orientation) {
+ default:
+ case LEFT_RIGHT:
+ return 0;
+ case BL_TR:
+ return 45;
+ case BOTTOM_TOP:
+ return 90;
+ case BR_TL:
+ return 135;
+ case RIGHT_LEFT:
+ return 180;
+ case TR_BL:
+ return 225;
+ case TOP_BOTTOM:
+ return 270;
+ case TL_BR:
+ return 315;
+ }
+ } else {
+ return 0;
+ }
+ }
+
public void setGradientColors(@Nullable int[] colors) {
mGradientColors = colors;
mSolidColors = null;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 9248ead..8092b1d 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -166,8 +166,6 @@
auto min_undequeued_buffers = static_cast<uint32_t>(query_value);
int bufferCount = min_undequeued_buffers + 2 + extraBuffers;
- ALOGD("Setting buffer count to %d, min_undequeued %u, extraBuffers %u",
- bufferCount, min_undequeued_buffers, extraBuffers);
native_window_set_buffer_count(window, bufferCount);
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index f326ce8..8551234 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -153,7 +153,8 @@
mNativeSurface = nullptr;
}
- if (mRenderAheadDepth == 0 && DeviceInfo::get()->getMaxRefreshRate() > 66.6f) {
+ if (mRenderAheadDepth == 0 && DeviceInfo::get()->getMaxRefreshRate() > 66.6f &&
+ !mFixedRenderAhead) {
mFixedRenderAhead = false;
mRenderAheadCapacity = 1;
} else {
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 1d55334..159cf49 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -235,8 +235,6 @@
}
void EglManager::loadConfigs() {
- ALOGD("Swap behavior %d", static_cast<int>(mSwapBehavior));
-
// Note: The default pixel format is RGBA_8888, when other formats are
// available, we should check the target pixel format and configure the
// attributes list properly.
@@ -246,7 +244,6 @@
// Try again without dirty regions enabled
ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
mSwapBehavior = SwapBehavior::Discard;
- ALOGD("Swap behavior %d", static_cast<int>(mSwapBehavior));
mEglConfig = load8BitsConfig(mEglDisplay, mSwapBehavior);
} else {
// Failed to get a valid config
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 62fd489..5173f63 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -167,8 +167,6 @@
LOG_ALWAYS_FATAL_IF(physDeviceProperties.apiVersion < VK_MAKE_VERSION(1, 1, 0));
mDriverVersion = physDeviceProperties.driverVersion;
- mIsQualcomm = physDeviceProperties.vendorID == 20803;
-
// query to get the initial queue props size
uint32_t queueCount;
mGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, nullptr);
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 31de803..dd3c6d0 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -179,13 +179,6 @@
SwapBehavior mSwapBehavior = SwapBehavior::Discard;
GrVkExtensions mExtensions;
uint32_t mDriverVersion = 0;
-
- // TODO: Remove once fix has landed. Temporaryly needed for workaround for setting up AHB
- // surfaces on Qualcomm. Currently if you don't use VkSwapchain Qualcomm is not setting
- // reporting that we need to use one of their private vendor usage bits which greatly effects
- // performance if it is not used.
- bool mIsQualcomm = false;
- bool isQualcomm() const { return mIsQualcomm; }
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index df6b9ed..b2cc23e 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -297,11 +297,6 @@
native_window_get_consumer_usage(window, &consumerUsage);
windowInfo.windowUsageFlags = consumerUsage | hwbUsage.androidHardwareBufferUsage;
- if (vkManager.isQualcomm()) {
- windowInfo.windowUsageFlags =
- windowInfo.windowUsageFlags | AHARDWAREBUFFER_USAGE_VENDOR_0;
- }
-
/*
* Now we attempt to modify the window!
*/
diff --git a/libs/protoutil/src/ProtoFileReader.cpp b/libs/protoutil/src/ProtoFileReader.cpp
index c7f1129..bbb1fe3 100644
--- a/libs/protoutil/src/ProtoFileReader.cpp
+++ b/libs/protoutil/src/ProtoFileReader.cpp
@@ -99,7 +99,6 @@
// Shouldn't get to here. Always call hasNext() before calling next().
return 0;
}
- mPos++;
return mBuffer[mOffset++];
}
@@ -131,7 +130,6 @@
const size_t chunk =
mMaxOffset - mOffset > amt ? amt : mMaxOffset - mOffset;
mOffset += chunk;
- mPos += chunk;
amt -= chunk;
}
}
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index b4be219..04e7bab 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -357,8 +357,10 @@
}
}
- // Sets the NI notification.
- private synchronized void setNiNotification(GpsNiNotification notif) {
+ /**
+ * Posts a notification in the status bar using the contents in {@code notif} object.
+ */
+ public synchronized void setNiNotification(GpsNiNotification notif) {
NotificationManager notificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null) {
@@ -539,14 +541,14 @@
*/
static private String decodeString(String original, boolean isHex, int coding)
{
+ if (coding == GPS_ENC_NONE) {
+ return original;
+ }
+
String decoded = original;
byte[] input = stringToByteArray(original, isHex);
switch (coding) {
- case GPS_ENC_NONE:
- decoded = original;
- break;
-
case GPS_ENC_SUPL_GSM_DEFAULT:
decoded = decodeGSMPackedString(input);
break;
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 8612e1b..a8f313b 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -716,24 +716,23 @@
}
/**
- * Specifies weather the audio may or may not be captured by other apps or the system.
+ * Specifies whether the audio may or may not be captured by other apps or the system.
*
* The default is {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}.
*
* There are multiple ways to set this policy:
- * - for each tracks independently, with this method
- * - application wide at runtime, with {@link AudioManager#setAllowedCapturePolicy(int)}
- * - application wide at build time, see {@code allowAudioPlaybackCapture} in the
- * application manifest.
+ * <ul>
+ * <li> for each track independently, with this method </li>
+ * <li> application-wide at runtime, with
+ * {@link AudioManager#setAllowedCapturePolicy(int)} </li>
+ * <li> application-wide at build time, see {@code allowAudioPlaybackCapture} in the
+ * application manifest. </li>
+ * </ul>
* The most restrictive policy is always applied.
*
- * See {@link AudioPlaybackCaptureConfiguration} for more details on the restrictions
+ * See {@link AudioPlaybackCaptureConfiguration} for more details on
* which audio signals can be captured.
*
- * @param capturePolicy one of
- * {@link #ALLOW_CAPTURE_BY_ALL},
- * {@link #ALLOW_CAPTURE_BY_SYSTEM},
- * {@link #ALLOW_CAPTURE_BY_NONE}.
* @return the same Builder instance
* @throws IllegalArgumentException if the argument is not a valid value.
*/
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index bcc57d2..2541982 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1484,20 +1484,22 @@
}
/**
- * Specifies wheather the audio played by this app may or may not be captured by other apps or
+ * Specifies whether the audio played by this app may or may not be captured by other apps or
* the system.
*
* The default is {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}.
*
* There are multiple ways to set this policy:
- * - for each tracks independently, see
- * {@link AudioAttributes.Builder#setAllowedCapturePolicy(int)}
- * - application wide at runtime, with this method
- * - application wide at build time, see {@code allowAudioPlaybackCapture} in the application
- * manifest.
+ * <ul>
+ * <li> for each track independently, see
+ * {@link AudioAttributes.Builder#setAllowedCapturePolicy(int)} </li>
+ * <li> application-wide at runtime, with this method </li>
+ * <li> application-wide at build time, see {@code allowAudioPlaybackCapture} in the application
+ * manifest. </li>
+ * </ul>
* The most restrictive policy is always applied.
*
- * See {@link AudioPlaybackCaptureConfiguration} for more details on the restrictions
+ * See {@link AudioPlaybackCaptureConfiguration} for more details on
* which audio signals can be captured.
*
* @param capturePolicy one of
@@ -3774,7 +3776,7 @@
/** @hide */
public static final int RECORD_CONFIG_EVENT_UPDATE = 2;
/** @hide */
- public static final int RECORD_CONFIG_EVENT_DEATH = 3;
+ public static final int RECORD_CONFIG_EVENT_RELEASE = 3;
/**
* keep in sync with frameworks/native/include/audiomanager/AudioManager.h
*/
diff --git a/media/java/android/media/AudioPlaybackCaptureConfiguration.java b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
index fe5005a..453704e 100644
--- a/media/java/android/media/AudioPlaybackCaptureConfiguration.java
+++ b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
@@ -34,21 +34,23 @@
* When capturing audio signals played by other apps (and yours),
* you will only capture a mix of the audio signals played by players
* (such as AudioTrack or MediaPlayer) which present the following characteristics:
- * - the usage value MUST be {@link AudioAttributes#USAGE_UNKNOWN} or
- * {@link AudioAttributes#USAGE_GAME}
- * or {@link AudioAttributes#USAGE_MEDIA}. All other usages CAN NOT be captured.
- * - AND the capture policy set by their app (with ${@link AudioManager#setAllowedCapturePolicy})
- * or on each player (with ${@link AudioAttributes.Builder#setAllowedCapturePolicy}) is
- * {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}, whichever is the most strict.
- * - AND their app attribute allowAudioPlaybackCapture in their manifest
- * MUST either be:
- * * set to "true"
- * * not set, and their {@code targetSdkVersion} MUST be equal or higher to
- * {@link android.os.Build.VERSION_CODES#Q}.
- * Ie. Apps that do not target at least Android Q must explicitly opt-in to be captured by a
- * MediaProjection.
- * - AND their apps MUST be in the same user profile as your app
- * (eg work profile can not capture user profile apps and vice-versa).
+ * <ul>
+ * <li> the usage value MUST be {@link AudioAttributes#USAGE_UNKNOWN} or
+ * {@link AudioAttributes#USAGE_GAME}
+ * or {@link AudioAttributes#USAGE_MEDIA}. All other usages CAN NOT be captured. </li>
+ * <li> AND the capture policy set by their app (with {@link AudioManager#setAllowedCapturePolicy})
+ * or on each player (with {@link AudioAttributes.Builder#setAllowedCapturePolicy}) is
+ * {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}, whichever is the most strict. </li>
+ * <li> AND their app attribute allowAudioPlaybackCapture in their manifest
+ * MUST either be: <ul>
+ * <li> set to "true" </li>
+ * <li> not set, and their {@code targetSdkVersion} MUST be equal to or greater than
+ * {@link android.os.Build.VERSION_CODES#Q}.
+ * Ie. Apps that do not target at least Android Q must explicitly opt-in to be captured
+ * by a MediaProjection. </li></ul>
+ * <li> AND their apps MUST be in the same user profile as your app
+ * (eg work profile cannot capture user profile apps and vice-versa). </li>
+ * </ul>
*
* <p>An example for creating a capture configuration for capturing all media playback:
*
@@ -56,7 +58,7 @@
* MediaProjection mediaProjection;
* // Retrieve a audio capable projection from the MediaProjectionManager
* AudioPlaybackCaptureConfiguration config =
- * new AudioPlaybackCaptureConfiguration.Builder(mediaProjection)
+ * new AudioPlaybackCaptureConfiguration.Builder(mediaProjection)
* .addMatchingUsage(AudioAttributes.USAGE_MEDIA)
* .build();
* AudioRecord record = new AudioRecord.Builder()
@@ -64,7 +66,8 @@
* .build();
* </pre>
*
- * @see MediaProjectionManager#getMediaProjection(int, Intent)
+ * @see Builder
+ * @see android.media.projection.MediaProjectionManager#getMediaProjection(int, Intent)
* @see AudioRecord.Builder#setAudioPlaybackCaptureConfig(AudioPlaybackCaptureConfiguration)
*/
public final class AudioPlaybackCaptureConfiguration {
@@ -80,7 +83,7 @@
/**
* @return the {@code MediaProjection} used to build this object.
- * @see {@code Builder.Builder}
+ * @see Builder#Builder(MediaProjection)
*/
public @NonNull MediaProjection getMediaProjection() {
return mProjection;
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index eeb7655..ce9b07d 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -838,6 +838,7 @@
}
if (mAudioCapturePolicy != null) {
AudioManager.unregisterAudioPolicyAsyncStatic(mAudioCapturePolicy);
+ mAudioCapturePolicy = null;
}
native_release();
mState = STATE_UNINITIALIZED;
diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java
index 74e6618..874a215 100644
--- a/media/java/android/media/AudioRecordingConfiguration.java
+++ b/media/java/android/media/AudioRecordingConfiguration.java
@@ -157,7 +157,7 @@
return new AudioRecordingConfiguration( /*anonymized uid*/ -1,
in.mClientSessionId, in.mClientSource, in.mClientFormat,
in.mDeviceFormat, in.mPatchHandle, "" /*empty package name*/,
- /*anonymized portId*/ -1, in.mClientSilenced, in.mDeviceSource, in.mClientEffects,
+ in.mClientPortId, in.mClientSilenced, in.mDeviceSource, in.mClientEffects,
in.mDeviceEffects);
}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 23db27d..31a6b81 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -233,6 +233,12 @@
public static final String TAG_NEW_SUBFILE_TYPE = "NewSubfileType";
/** Type is String. */
public static final String TAG_OECF = "OECF";
+ /** Type is String. {@hide} */
+ public static final String TAG_OFFSET_TIME = "OffsetTime";
+ /** Type is String. {@hide} */
+ public static final String TAG_OFFSET_TIME_ORIGINAL = "OffsetTimeOriginal";
+ /** Type is String. {@hide} */
+ public static final String TAG_OFFSET_TIME_DIGITIZED = "OffsetTimeDigitized";
/** Type is int. */
public static final String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
/** Type is int. */
@@ -486,6 +492,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private static SimpleDateFormat sFormatter;
+ private static SimpleDateFormat sFormatterTz;
// See Exchangeable image file format for digital still cameras: Exif version 2.2.
// The following values are for parsing EXIF data area. There are tag groups in EXIF data area.
@@ -1041,6 +1048,9 @@
new ExifTag(TAG_EXIF_VERSION, 36864, IFD_FORMAT_STRING),
new ExifTag(TAG_DATETIME_ORIGINAL, 36867, IFD_FORMAT_STRING),
new ExifTag(TAG_DATETIME_DIGITIZED, 36868, IFD_FORMAT_STRING),
+ new ExifTag(TAG_OFFSET_TIME, 36880, IFD_FORMAT_STRING),
+ new ExifTag(TAG_OFFSET_TIME_ORIGINAL, 36881, IFD_FORMAT_STRING),
+ new ExifTag(TAG_OFFSET_TIME_DIGITIZED, 36882, IFD_FORMAT_STRING),
new ExifTag(TAG_COMPONENTS_CONFIGURATION, 37121, IFD_FORMAT_UNDEFINED),
new ExifTag(TAG_COMPRESSED_BITS_PER_PIXEL, 37122, IFD_FORMAT_URATIONAL),
new ExifTag(TAG_SHUTTER_SPEED_VALUE, 37377, IFD_FORMAT_SRATIONAL),
@@ -1301,6 +1311,8 @@
static {
sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+ sFormatterTz = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss XXX");
+ sFormatterTz.setTimeZone(TimeZone.getTimeZone("UTC"));
// Build up the hash tables to look up Exif tags for reading Exif tags.
for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
@@ -2140,7 +2152,8 @@
@UnsupportedAppUsage
public @CurrentTimeMillisLong long getDateTime() {
return parseDateTime(getAttribute(TAG_DATETIME),
- getAttribute(TAG_SUBSEC_TIME));
+ getAttribute(TAG_SUBSEC_TIME),
+ getAttribute(TAG_OFFSET_TIME));
}
/**
@@ -2151,7 +2164,8 @@
*/
public @CurrentTimeMillisLong long getDateTimeDigitized() {
return parseDateTime(getAttribute(TAG_DATETIME_DIGITIZED),
- getAttribute(TAG_SUBSEC_TIME_DIGITIZED));
+ getAttribute(TAG_SUBSEC_TIME_DIGITIZED),
+ getAttribute(TAG_OFFSET_TIME_DIGITIZED));
}
/**
@@ -2163,11 +2177,12 @@
@UnsupportedAppUsage
public @CurrentTimeMillisLong long getDateTimeOriginal() {
return parseDateTime(getAttribute(TAG_DATETIME_ORIGINAL),
- getAttribute(TAG_SUBSEC_TIME_ORIGINAL));
+ getAttribute(TAG_SUBSEC_TIME_ORIGINAL),
+ getAttribute(TAG_OFFSET_TIME_ORIGINAL));
}
private static @CurrentTimeMillisLong long parseDateTime(@Nullable String dateTimeString,
- @Nullable String subSecs) {
+ @Nullable String subSecs, @Nullable String offsetString) {
if (dateTimeString == null
|| !sNonZeroTimePattern.matcher(dateTimeString).matches()) return -1;
@@ -2176,6 +2191,13 @@
// The exif field is in local time. Parsing it as if it is UTC will yield time
// since 1/1/1970 local time
Date datetime = sFormatter.parse(dateTimeString, pos);
+
+ if (offsetString != null) {
+ dateTimeString = dateTimeString + " " + offsetString;
+ ParsePosition position = new ParsePosition(0);
+ datetime = sFormatterTz.parse(dateTimeString, position);
+ }
+
if (datetime == null) return -1;
long msecs = datetime.getTime();
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 81ddcdb4..a790441 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -64,6 +64,8 @@
oneway void recorderEvent(in int riid, in int event);
+ oneway void releaseRecorder(in int riid);
+
// Java-only methods below.
oneway void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index c09bd79..56e8e85 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -1659,6 +1659,7 @@
private final Object mListenerLock = new Object();
private MediaCodecInfo mCodecInfo;
private final Object mCodecInfoLock = new Object();
+ private MediaCrypto mCrypto;
private static final int EVENT_CALLBACK = 1;
private static final int EVENT_SET_CALLBACK = 2;
@@ -1858,6 +1859,7 @@
@Override
protected void finalize() {
native_finalize();
+ mCrypto = null;
}
/**
@@ -1873,6 +1875,7 @@
public final void reset() {
freeAllTrackedBuffers(); // free buffers first
native_reset();
+ mCrypto = null;
}
private native final void native_reset();
@@ -1887,6 +1890,7 @@
public final void release() {
freeAllTrackedBuffers(); // free buffers first
native_release();
+ mCrypto = null;
}
private native final void native_release();
@@ -1916,6 +1920,10 @@
* @param crypto Specify a crypto object to facilitate secure decryption
* of the media data. Pass {@code null} as {@code crypto} for
* non-secure codecs.
+ * Please note that {@link MediaCodec} does NOT take ownership
+ * of the {@link MediaCrypto} object; it is the application's
+ * responsibility to properly cleanup the {@link MediaCrypto} object
+ * when not in use.
* @param flags Specify {@link #CONFIGURE_FLAG_ENCODE} to configure the
* component as an encoder.
* @throws IllegalArgumentException if the surface has been released (or is invalid),
@@ -2000,6 +2008,7 @@
}
mHasSurface = surface != null;
+ mCrypto = crypto;
native_configure(keys, values, surface, crypto, descramblerBinder, flags);
}
diff --git a/media/java/android/media/MediaParceledListSlice.aidl b/media/java/android/media/MediaParceledListSlice.aidl
deleted file mode 100644
index 5c0e5bc..0000000
--- a/media/java/android/media/MediaParceledListSlice.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/** @hide */
-parcelable MediaParceledListSlice;
diff --git a/media/java/android/media/MediaParceledListSlice.java b/media/java/android/media/MediaParceledListSlice.java
deleted file mode 100644
index e90d9a4..0000000
--- a/media/java/android/media/MediaParceledListSlice.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Transfer a large list of objects across an IPC. Splits into multiple transactions if needed.
- * Note: Only use classes declared final in order to avoid subclasses overriding reading/writing
- * parcel logic.
- *
- * TODO: Add test for sending large data
- * @param <T> A Parcelable class which will be sent over the binder calls.
- * @hide
- */
-public class MediaParceledListSlice<T extends Parcelable> implements Parcelable {
- private static final String TAG = "MediaParceledListSlice";
- private static final boolean DEBUG = false;
-
- private static final int MAX_IPC_SIZE = 64 * 1024; // IBinder.MAX_IPC_SIZE
-
- final List<T> mList;
-
- public MediaParceledListSlice(List<T> list) {
- if (list == null) {
- throw new IllegalArgumentException("list shouldn't be null");
- }
- mList = list;
- }
-
- MediaParceledListSlice(Parcel p) {
- final int itemCount = p.readInt();
- mList = new ArrayList<>(itemCount);
- if (DEBUG) {
- Log.d(TAG, "Retrieving " + itemCount + " items");
- }
- if (itemCount <= 0) {
- return;
- }
-
- int i = 0;
- while (i < itemCount) {
- if (p.readInt() == 0) {
- break;
- }
-
- final T parcelable = p.readParcelable(null);
- mList.add(parcelable);
-
- if (DEBUG) {
- Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size() - 1));
- }
- i++;
- }
- if (i >= itemCount) {
- return;
- }
- final IBinder retriever = p.readStrongBinder();
- while (i < itemCount) {
- if (DEBUG) {
- Log.d(TAG, "Reading more @" + i + " of " + itemCount + ": retriever=" + retriever);
- }
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInt(i);
- try {
- retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
- } catch (RemoteException e) {
- Log.w(TAG, "Failure retrieving array; only received " + i + " of " + itemCount, e);
- return;
- }
- while (i < itemCount && reply.readInt() != 0) {
- final T parcelable = reply.readParcelable(null);
- mList.add(parcelable);
-
- if (DEBUG) {
- Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size() - 1));
- }
- i++;
- }
- reply.recycle();
- data.recycle();
- }
- }
-
- public List<T> getList() {
- return mList;
- }
-
- /**
- * Write this to another Parcel. Note that this discards the internal Parcel
- * and should not be used anymore. This is so we can pass this to a Binder
- * where we won't have a chance to call recycle on this.
- */
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- final int itemCount = mList.size();
- dest.writeInt(itemCount);
- if (DEBUG) {
- Log.d(TAG, "Writing " + itemCount + " items");
- }
- if (itemCount > 0) {
- int i = 0;
- while (i < itemCount && dest.dataSize() < MAX_IPC_SIZE) {
- dest.writeInt(1);
-
- final T parcelable = mList.get(i);
- dest.writeParcelable(parcelable, flags);
-
- if (DEBUG) {
- Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i));
- }
- i++;
- }
- if (i < itemCount) {
- dest.writeInt(0);
- Binder retriever = new Binder() {
- @Override
- protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- if (code != FIRST_CALL_TRANSACTION) {
- return super.onTransact(code, data, reply, flags);
- }
- int i = data.readInt();
- if (DEBUG) {
- Log.d(TAG, "Writing more @" + i + " of " + itemCount);
- }
- while (i < itemCount && reply.dataSize() < MAX_IPC_SIZE) {
- reply.writeInt(1);
-
- final T parcelable = mList.get(i);
- reply.writeParcelable(parcelable, flags);
-
- if (DEBUG) {
- Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i));
- }
- i++;
- }
- if (i < itemCount) {
- if (DEBUG) {
- Log.d(TAG, "Breaking @" + i + " of " + itemCount);
- }
- reply.writeInt(0);
- }
- return true;
- }
- };
- if (DEBUG) {
- Log.d(TAG, "Breaking @" + i + " of " + itemCount + ": retriever=" + retriever);
- }
- dest.writeStrongBinder(retriever);
- }
- }
- }
-
- @Override
- public int describeContents() {
- int contents = 0;
- final List<T> list = getList();
- for (int i = 0; i < list.size(); i++) {
- contents |= list.get(i).describeContents();
- }
- return contents;
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<MediaParceledListSlice> CREATOR =
- new Parcelable.Creator<MediaParceledListSlice>() {
- @Override
- public MediaParceledListSlice createFromParcel(Parcel in) {
- return new MediaParceledListSlice(in);
- }
-
- @Override
- public MediaParceledListSlice[] newArray(int size) {
- return new MediaParceledListSlice[size];
- }
- };
-}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 1937edd..353e58e 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -629,7 +629,6 @@
private boolean mStayAwake;
private int mStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
private int mUsage = -1;
- private boolean mBypassInterruptionPolicy;
// Modular DRM
private UUID mDrmUUID;
@@ -2218,8 +2217,6 @@
}
baseUpdateAudioAttributes(attributes);
mUsage = attributes.getUsage();
- mBypassInterruptionPolicy = (attributes.getAllFlags()
- & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0;
Parcel pattributes = Parcel.obtain();
attributes.writeToParcel(pattributes, AudioAttributes.FLATTEN_TAGS);
setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, pattributes);
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 77f756b..68c0a22 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -33,7 +33,6 @@
import android.content.pm.UserInfo;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
-import android.media.MediaScannerConnection.MediaScannerConnectionClient;
import android.net.Uri;
import android.os.Environment;
import android.os.FileUtils;
@@ -50,7 +49,6 @@
import com.android.internal.database.SortCursor;
-import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -59,7 +57,6 @@
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.LinkedBlockingQueue;
/**
* RingtoneManager provides access to ringtones, notification, and other types
@@ -927,11 +924,7 @@
}
// Tell MediaScanner about the new file. Wait for it to assign a {@link Uri}.
- try (NewRingtoneScanner scanner = new NewRingtoneScanner(outFile)) {
- return scanner.take();
- } catch (InterruptedException e) {
- throw new IOException("Audio file failed to scan as a ringtone", e);
- }
+ return MediaStore.scanFile(mContext, outFile);
}
private static final String getExternalDirectoryForType(final int type) {
@@ -1109,53 +1102,6 @@
}
/**
- * Creates a {@link android.media.MediaScannerConnection} to scan a ringtone file and add its
- * information to the internal database.
- *
- * It uses a {@link java.util.concurrent.LinkedBlockingQueue} so that the caller can block until
- * the scan is completed.
- */
- private class NewRingtoneScanner implements Closeable, MediaScannerConnectionClient {
- private MediaScannerConnection mMediaScannerConnection;
- private File mFile;
- private LinkedBlockingQueue<Uri> mQueue = new LinkedBlockingQueue<>(1);
-
- public NewRingtoneScanner(File file) {
- mFile = file;
- mMediaScannerConnection = new MediaScannerConnection(mContext, this);
- mMediaScannerConnection.connect();
- }
-
- @Override
- public void close() {
- mMediaScannerConnection.disconnect();
- }
-
- @Override
- public void onMediaScannerConnected() {
- mMediaScannerConnection.scanFile(mFile.getAbsolutePath(), null);
- }
-
- @Override
- public void onScanCompleted(String path, Uri uri) {
- if (uri == null) {
- // There was some issue with scanning. Delete the copied file so it is not oprhaned.
- mFile.delete();
- return;
- }
- try {
- mQueue.put(uri);
- } catch (InterruptedException e) {
- Log.e(TAG, "Unable to put new ringtone Uri in queue", e);
- }
- }
-
- public Uri take() throws InterruptedException {
- return mQueue.take();
- }
- }
-
- /**
* Attempts to create a context for the given user.
*
* @return created context, or null if package does not exist
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 5de56c7..b3c2bb7 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -52,6 +52,7 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.Objects;
import java.util.function.ToIntFunction;
/**
@@ -369,10 +370,12 @@
// If we're okay with something larger than native format, just
// return a frame without up-scaling it
if (size.getWidth() > width && size.getHeight() > height) {
- return mmr.getFrameAtTime(duration / 2, OPTION_CLOSEST_SYNC);
+ return Objects.requireNonNull(
+ mmr.getFrameAtTime(duration / 2, OPTION_CLOSEST_SYNC));
} else {
- return mmr.getScaledFrameAtTime(duration / 2, OPTION_CLOSEST_SYNC,
- size.getWidth(), size.getHeight());
+ return Objects.requireNonNull(
+ mmr.getScaledFrameAtTime(duration / 2, OPTION_CLOSEST_SYNC,
+ size.getWidth(), size.getHeight()));
}
} catch (RuntimeException e) {
throw new IOException("Failed to create thumbnail", e);
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 65255a1..3c2be5f 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -23,8 +23,8 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.ParceledListSlice;
import android.media.MediaDescription;
-import android.media.MediaParceledListSlice;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.os.Binder;
@@ -653,7 +653,7 @@
}
private void onLoadChildren(final IMediaBrowserServiceCallbacks callback,
- final String parentId, final MediaParceledListSlice list, final Bundle options) {
+ final String parentId, final ParceledListSlice list, final Bundle options) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -1107,12 +1107,12 @@
}
@Override
- public void onLoadChildren(String parentId, MediaParceledListSlice list) {
+ public void onLoadChildren(String parentId, ParceledListSlice list) {
onLoadChildrenWithOptions(parentId, list, null);
}
@Override
- public void onLoadChildrenWithOptions(String parentId, MediaParceledListSlice list,
+ public void onLoadChildrenWithOptions(String parentId, ParceledListSlice list,
final Bundle options) {
MediaBrowser mediaBrowser = mMediaBrowser.get();
if (mediaBrowser != null) {
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index fcde95a..4d68a6a 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -16,9 +16,9 @@
package android.media.session;
import android.app.PendingIntent;
+import android.content.pm.ParceledListSlice;
import android.media.AudioAttributes;
import android.media.MediaMetadata;
-import android.media.MediaParceledListSlice;
import android.media.session.ISessionController;
import android.media.session.PlaybackState;
import android.media.session.MediaSession;
@@ -41,7 +41,7 @@
// These commands are for the TransportPerformer
void setMetadata(in MediaMetadata metadata, long duration, String metadataDescription);
void setPlaybackState(in PlaybackState state);
- void setQueue(in MediaParceledListSlice queue);
+ void setQueue(in ParceledListSlice queue);
void setQueueTitle(CharSequence title);
void setExtras(in Bundle extras);
void setRatingType(int type);
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 9b1223c..e1039fd 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -17,8 +17,8 @@
import android.app.PendingIntent;
import android.content.Intent;
+import android.content.pm.ParceledListSlice;
import android.media.MediaMetadata;
-import android.media.MediaParceledListSlice;
import android.media.Rating;
import android.media.session.ISessionControllerCallback;
import android.media.session.MediaController;
@@ -82,7 +82,7 @@
String action, in Bundle args);
MediaMetadata getMetadata();
PlaybackState getPlaybackState();
- MediaParceledListSlice getQueue();
+ ParceledListSlice getQueue();
CharSequence getQueueTitle();
Bundle getExtras();
int getRatingType();
diff --git a/media/java/android/media/session/ISessionControllerCallback.aidl b/media/java/android/media/session/ISessionControllerCallback.aidl
index f284133..9da3e3b 100644
--- a/media/java/android/media/session/ISessionControllerCallback.aidl
+++ b/media/java/android/media/session/ISessionControllerCallback.aidl
@@ -15,8 +15,8 @@
package android.media.session;
+import android.content.pm.ParceledListSlice;
import android.media.MediaMetadata;
-import android.media.MediaParceledListSlice;
import android.media.session.MediaController;
import android.media.session.PlaybackState;
import android.os.Bundle;
@@ -31,7 +31,7 @@
// These callbacks are for the TransportController
void onPlaybackStateChanged(in PlaybackState state);
void onMetadataChanged(in MediaMetadata metadata);
- void onQueueChanged(in MediaParceledListSlice queue);
+ void onQueueChanged(in ParceledListSlice queue);
void onQueueTitleChanged(CharSequence title);
void onExtrasChanged(in Bundle extras);
void onVolumeInfoChanged(in MediaController.PlaybackInfo info);
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 3500475..c1c7fca 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -21,10 +21,10 @@
import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
import android.content.Context;
+import android.content.pm.ParceledListSlice;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.MediaMetadata;
-import android.media.MediaParceledListSlice;
import android.media.Rating;
import android.media.VolumeProvider;
import android.media.session.MediaSession.QueueItem;
@@ -174,7 +174,7 @@
*/
public @Nullable List<MediaSession.QueueItem> getQueue() {
try {
- MediaParceledListSlice list = mSessionBinder.getQueue();
+ ParceledListSlice list = mSessionBinder.getQueue();
return list == null ? null : list.getList();
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling getQueue.", e);
@@ -891,11 +891,16 @@
}
/**
- * Set the playback speed.
+ * Sets the playback speed. A value of {@code 1.0f} is the default playback value,
+ * and a negative value indicates reverse playback. {@code 0.0f} is not allowed.
*
* @param speed The playback speed
+ * @throws IllegalArgumentException if the {@code speed} is equal to zero.
*/
public void setPlaybackSpeed(float speed) {
+ if (speed == 0.0f) {
+ throw new IllegalArgumentException("speed must not be zero");
+ }
try {
mSessionBinder.setPlaybackSpeed(mContext.getPackageName(), mCbStub, speed);
} catch (RemoteException e) {
@@ -1111,7 +1116,7 @@
}
@Override
- public void onQueueChanged(MediaParceledListSlice queue) {
+ public void onQueueChanged(ParceledListSlice queue) {
MediaController controller = mController.get();
if (controller != null) {
controller.postMessage(MSG_UPDATE_QUEUE, queue, null);
@@ -1169,7 +1174,7 @@
break;
case MSG_UPDATE_QUEUE:
mCallback.onQueueChanged(msg.obj == null ? null :
- (List<QueueItem>) ((MediaParceledListSlice) msg.obj).getList());
+ (List<QueueItem>) ((ParceledListSlice) msg.obj).getList());
break;
case MSG_UPDATE_QUEUE_TITLE:
mCallback.onQueueTitleChanged((CharSequence) msg.obj);
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index c577469..c4085f8 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -24,10 +24,10 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ParceledListSlice;
import android.media.AudioAttributes;
import android.media.MediaDescription;
import android.media.MediaMetadata;
-import android.media.MediaParceledListSlice;
import android.media.Rating;
import android.media.VolumeProvider;
import android.media.session.MediaSessionManager.RemoteUserInfo;
@@ -473,7 +473,7 @@
*/
public void setQueue(@Nullable List<QueueItem> queue) {
try {
- mBinder.setQueue(queue == null ? null : new MediaParceledListSlice(queue));
+ mBinder.setQueue(queue == null ? null : new ParceledListSlice(queue));
} catch (RemoteException e) {
Log.wtf("Dead object in setQueue.", e);
}
@@ -1084,6 +1084,9 @@
* To update the new playback speed, create a new {@link PlaybackState} by using {@link
* PlaybackState.Builder#setState(int, long, float)}, and set it with
* {@link #setPlaybackState(PlaybackState)}.
+ * <p>
+ * A value of {@code 1.0f} is the default playback value, and a negative value indicates
+ * reverse playback. The {@code speed} will not be equal to zero.
*
* @param speed the playback speed
* @see #setPlaybackState(PlaybackState)
diff --git a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
index 507a8f7..8238b8c 100644
--- a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
+++ b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
@@ -2,7 +2,7 @@
package android.service.media;
-import android.media.MediaParceledListSlice;
+import android.content.pm.ParceledListSlice;
import android.media.session.MediaSession;
import android.os.Bundle;
@@ -21,7 +21,7 @@
*/
void onConnect(String root, in MediaSession.Token session, in Bundle extras);
void onConnectFailed();
- void onLoadChildren(String mediaId, in MediaParceledListSlice list);
- void onLoadChildrenWithOptions(String mediaId, in MediaParceledListSlice list,
+ void onLoadChildren(String mediaId, in ParceledListSlice list);
+ void onLoadChildrenWithOptions(String mediaId, in ParceledListSlice list,
in Bundle options);
}
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index d9ef6ae..86a1076 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -25,7 +25,7 @@
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.media.MediaParceledListSlice;
+import android.content.pm.ParceledListSlice;
import android.media.browse.MediaBrowser;
import android.media.browse.MediaBrowserUtils;
import android.media.session.MediaSession;
@@ -684,8 +684,8 @@
List<MediaBrowser.MediaItem> filteredList =
(flag & RESULT_FLAG_OPTION_NOT_HANDLED) != 0
? applyOptions(list, options) : list;
- final MediaParceledListSlice<MediaBrowser.MediaItem> pls =
- filteredList == null ? null : new MediaParceledListSlice<>(filteredList);
+ final ParceledListSlice<MediaBrowser.MediaItem> pls =
+ filteredList == null ? null : new ParceledListSlice<>(filteredList);
try {
connection.callbacks.onLoadChildrenWithOptions(parentId, pls, options);
} catch (RemoteException ex) {
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index 9add247..86d6d44 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -18,7 +18,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.captiveportallogin"
- android:versionCode="210000000"
+ android:versionCode="220000000"
android:versionName="Q-initial">
<uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
@@ -31,6 +31,7 @@
<uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
<application android:label="@string/app_name"
+ android:icon="@drawable/app_icon"
android:usesCleartextTraffic="true"
android:supportsRtl="true" >
<activity
diff --git a/packages/CaptivePortalLogin/res/drawable/app_icon.xml b/packages/CaptivePortalLogin/res/drawable/app_icon.xml
new file mode 100644
index 0000000..456ca83
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/drawable/app_icon.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2019 The Android Open 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.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background>
+ <color android:color="@*android:color/accent_device_default_light" />
+ </background>
+ <foreground>
+ <inset
+ android:drawable="@drawable/maybe_wifi"
+ android:inset="25%">
+ </inset>
+ </foreground>
+</adaptive-icon>
diff --git a/packages/CaptivePortalLogin/res/drawable/maybe_wifi.xml b/packages/CaptivePortalLogin/res/drawable/maybe_wifi.xml
new file mode 100644
index 0000000..207aade
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/drawable/maybe_wifi.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="26.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="26.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M19.1,14l-3.4,0l0,-1.5c0,-1.8 0.8,-2.8 1.5,-3.4C18.1,8.3 19.200001,8 20.6,8c1.2,0 2.3,0.3 3.1,0.8l1.9,-2.3C25.1,6.1 20.299999,2.1 13,2.1S0.9,6.1 0.4,6.5L13,22l0,0l0,0l0,0l0,0l6.5,-8.1L19.1,14z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M19.5,17.799999c0,-0.8 0.1,-1.3 0.2,-1.6c0.2,-0.3 0.5,-0.7 1.1,-1.2c0.4,-0.4 0.7,-0.8 1,-1.1s0.4,-0.8 0.4,-1.2c0,-0.5 -0.1,-0.9 -0.4,-1.2c-0.3,-0.3 -0.7,-0.4 -1.2,-0.4c-0.4,0 -0.8,0.1 -1.1,0.3c-0.3,0.2 -0.4,0.6 -0.4,1.1l-1.9,0c0,-1 0.3,-1.7 1,-2.2c0.6,-0.5 1.5,-0.8 2.5,-0.8c1.1,0 2,0.3 2.6,0.8c0.6,0.5 0.9,1.3 0.9,2.3c0,0.7 -0.2,1.3 -0.6,1.8c-0.4,0.6 -0.9,1.1 -1.5,1.6c-0.3,0.3 -0.5,0.5 -0.6,0.7c-0.1,0.2 -0.1,0.6 -0.1,1L19.5,17.700001zM21.4,21l-1.9,0l0,-1.8l1.9,0L21.4,21z"/>
+</vector>
diff --git a/packages/CarSystemUI/AndroidManifest.xml b/packages/CarSystemUI/AndroidManifest.xml
index 4e8a3a3..195d4fe 100644
--- a/packages/CarSystemUI/AndroidManifest.xml
+++ b/packages/CarSystemUI/AndroidManifest.xml
@@ -19,6 +19,6 @@
package="com.android.systemui"
android:sharedUserId="android.uid.systemui"
coreApp="true">
-
-
+ <!-- This permission is required to monitor car power state. -->
+ <uses-permission android:name="android.car.permission.CAR_POWER" />
</manifest>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
index d20038d..5f99e17 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
@@ -22,7 +22,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.util.Log;
+import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
@@ -112,9 +112,11 @@
*/
public void taskChanged(List<ActivityManager.StackInfo> stackInfoList) {
ActivityManager.StackInfo validStackInfo = null;
- for (ActivityManager.StackInfo stackInfo :stackInfoList) {
- // Find the first stack info with a topActivity
- if (stackInfo.topActivity != null) {
+ for (ActivityManager.StackInfo stackInfo : stackInfoList) {
+ // Find the first stack info with a topActivity in the primary display.
+ // TODO: We assume that CarFacetButton will launch an app only in the primary display.
+ // We need to extend the functionality to handle the mutliple display properly.
+ if (stackInfo.topActivity != null && stackInfo.displayId == Display.DEFAULT_DISPLAY) {
validStackInfo = stackInfo;
break;
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 12b41ca..f5dab01 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -25,6 +25,7 @@
import android.car.Car;
import android.car.drivingstate.CarDrivingStateEvent;
import android.car.drivingstate.CarUxRestrictionsManager;
+import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -36,6 +37,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.ViewTreeObserver;
import android.view.WindowManager;
import androidx.annotation.NonNull;
@@ -59,7 +61,7 @@
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.classifier.FalsingLog;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.car.CarQSFragment;
@@ -120,12 +122,17 @@
private boolean mDeviceIsProvisioned = true;
private HvacController mHvacController;
private DrivingStateHelper mDrivingStateHelper;
- private static FlingAnimationUtils sFlingAnimationUtils;
+ private PowerManagerHelper mPowerManagerHelper;
+ private FlingAnimationUtils mFlingAnimationUtils;
private SwitchToGuestTimer mSwitchToGuestTimer;
+ private NotificationDataManager mNotificationDataManager;
+ private NotificationClickHandlerFactory mNotificationClickHandlerFactory;
// The container for the notifications.
private CarNotificationView mNotificationView;
private RecyclerView mNotificationList;
+ // The controller for the notification view.
+ private NotificationViewController mNotificationViewController;
// The state of if the notification list is currently showing the bottom.
private boolean mNotificationListAtBottom;
// Was the notification list at the bottom when the user first touched the screen
@@ -155,6 +162,20 @@
// If notification shade is being swiped vertically to close.
private boolean mIsSwipingVerticallyToClose;
+ private final CarPowerStateListener mCarPowerStateListener =
+ (int state) -> {
+ // When the car powers on, clear all notifications and mute/unread states.
+ Log.d(TAG, "New car power state: " + state);
+ if (state == CarPowerStateListener.ON) {
+ if (mNotificationClickHandlerFactory != null) {
+ mNotificationClickHandlerFactory.clearAllNotifications();
+ }
+ if (mNotificationDataManager != null) {
+ mNotificationDataManager.clearAll();
+ }
+ }
+ };
+
@Override
public void start() {
// get the provisioned state before calling the parent class since it's that flow that
@@ -171,7 +192,7 @@
R.integer.notification_settle_open_percentage);
mSettleClosePercentage = mContext.getResources().getInteger(
R.integer.notification_settle_close_percentage);
- sFlingAnimationUtils = new FlingAnimationUtils(mContext,
+ mFlingAnimationUtils = new FlingAnimationUtils(mContext,
FLING_ANIMATION_MAX_TIME, FLING_SPEED_UP_FACTOR);
createBatteryController();
@@ -203,6 +224,9 @@
mDrivingStateHelper = new DrivingStateHelper(mContext, this::onDrivingStateChanged);
mDrivingStateHelper.connectToCarService();
+ mPowerManagerHelper = new PowerManagerHelper(mContext, mCarPowerStateListener);
+ mPowerManagerHelper.connectToCarService();
+
mSwitchToGuestTimer = new SwitchToGuestTimer(mContext);
}
@@ -307,7 +331,6 @@
}
}
-
@Override
protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
super.makeStatusBarView(result);
@@ -406,7 +429,7 @@
}
);
- NotificationClickHandlerFactory clickHandlerFactory = new NotificationClickHandlerFactory(
+ mNotificationClickHandlerFactory = new NotificationClickHandlerFactory(
mBarService,
launchResult -> {
if (launchResult == ActivityManager.START_TASK_TO_FRONT
@@ -421,17 +444,27 @@
CarUxRestrictionManagerWrapper carUxRestrictionManagerWrapper =
new CarUxRestrictionManagerWrapper();
carUxRestrictionManagerWrapper.setCarUxRestrictionsManager(carUxRestrictionsManager);
- NotificationDataManager notificationDataManager = new NotificationDataManager();
+
+ mNotificationDataManager = new NotificationDataManager();
+ mNotificationDataManager.setOnUnseenCountUpdateListener(
+ () -> {
+ // TODO: Update Notification Icon based on unseen count
+ Log.d(TAG, "unseen count: " +
+ mNotificationDataManager.getUnseenNotificationCount());
+ });
+
CarHeadsUpNotificationManager carHeadsUpNotificationManager =
- new CarSystemUIHeadsUpNotificationManager(mContext, clickHandlerFactory,
- notificationDataManager);
+ new CarSystemUIHeadsUpNotificationManager(mContext,
+ mNotificationClickHandlerFactory, mNotificationDataManager);
+ mNotificationClickHandlerFactory.setNotificationDataManager(mNotificationDataManager);
carNotificationListener.registerAsSystemService(mContext, carUxRestrictionManagerWrapper,
- carHeadsUpNotificationManager, notificationDataManager);
+ carHeadsUpNotificationManager, mNotificationDataManager);
mNotificationView = mStatusBarWindow.findViewById(R.id.notification_view);
View glassPane = mStatusBarWindow.findViewById(R.id.glass_pane);
- mNotificationView.setClickHandlerFactory(clickHandlerFactory);
+ mNotificationView.setClickHandlerFactory(mNotificationClickHandlerFactory);
+ mNotificationView.setNotificationDataManager(mNotificationDataManager);
// The glass pane is used to view touch events before passed to the notification list.
// This allows us to initialize gesture listeners and detect when to close the notifications
@@ -513,11 +546,12 @@
}
});
- NotificationViewController mNotificationViewController = new NotificationViewController(
+ mNotificationViewController = new NotificationViewController(
mNotificationView,
PreprocessingManager.getInstance(mContext),
carNotificationListener,
- carUxRestrictionManagerWrapper);
+ carUxRestrictionManagerWrapper,
+ mNotificationDataManager);
mNotificationViewController.enable();
}
@@ -537,7 +571,6 @@
mNotificationList.scrollToPosition(0);
mStatusBarWindowController.setPanelVisible(true);
mNotificationView.setVisibility(View.VISIBLE);
-
animateNotificationPanel(mOpeningVelocity, false);
setPanelExpanded(true);
@@ -570,15 +603,33 @@
* notification shade this method also makes the view invisible after animation ends.
*/
private void animateNotificationPanel(float velocity, boolean isClosing) {
- Rect rect = mNotificationList.getClipBounds();
- if (rect == null) {
- return;
- }
- float from = rect.bottom;
float to = 0;
if (!isClosing) {
to = mNotificationView.getHeight();
}
+
+ Rect rect = mNotificationList.getClipBounds();
+ if (rect != null) {
+ float from = rect.bottom;
+ animate(from, to, velocity, isClosing);
+ return;
+ }
+
+ // We will only be here if the shade is being opened programmatically.
+ ViewTreeObserver notificationTreeObserver = mNotificationView.getViewTreeObserver();
+ notificationTreeObserver.addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ ViewTreeObserver obs = mNotificationView.getViewTreeObserver();
+ obs.removeOnGlobalLayoutListener(this);
+ float to = mNotificationView.getHeight();
+ animate(/* from= */ 0, to, velocity, isClosing);
+ }
+ });
+ }
+
+ private void animate(float from, float to, float velocity, boolean isClosing) {
if (mIsNotificationAnimating) {
return;
}
@@ -602,15 +653,18 @@
mStatusBarWindowController.setPanelVisible(false);
mNotificationView.setVisibility(View.INVISIBLE);
mNotificationList.setClipBounds(null);
+ mNotificationViewController.setIsInForeground(false);
// let the status bar know that the panel is closed
setPanelExpanded(false);
} else {
+ mNotificationViewController.setIsInForeground(true);
// let the status bar know that the panel is open
+ mNotificationView.setVisibleNotificationsAsSeen();
setPanelExpanded(true);
}
}
});
- sFlingAnimationUtils.apply(animator, from, to, Math.abs(velocity));
+ mFlingAnimationUtils.apply(animator, from, to, Math.abs(velocity));
animator.start();
}
@@ -794,7 +848,7 @@
KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args);
}
- FalsingManager.getInstance(mContext).dump(pw);
+ FalsingManagerFactory.getInstance(mContext).dump(pw);
FalsingLog.dump(pw);
pw.println("SharedPreferences:");
@@ -806,7 +860,6 @@
}
}
-
@Override
public void showBatteryView() {
if (Log.isLoggable(TAG, Log.DEBUG)) {
@@ -951,12 +1004,10 @@
return mContext.getDrawable(com.android.internal.R.drawable.default_wallpaper);
}
- /** Returns true if the current user makes it through the setup wizard, false otherwise. */
- private boolean getIsUserSetup() {
- return mUserSetup;
- }
-
private void setNotificationViewClipBounds(int height) {
+ if (height > mNotificationView.getHeight()) {
+ height = mNotificationView.getHeight();
+ }
Rect clipBounds = new Rect();
clipBounds.set(0, 0, mNotificationView.getWidth(), height);
// Sets the clip region on the notification list view.
@@ -980,7 +1031,6 @@
}
}
- private static final int SWIPE_UP_MIN_DISTANCE = 75;
private static final int SWIPE_DOWN_MIN_DISTANCE = 25;
private static final int SWIPE_MAX_OFF_PATH = 75;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
@@ -1035,8 +1085,10 @@
@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
- animateNotificationPanel(DEFAULT_FLING_VELOCITY, true);
- return false;
+ if (mPanelExpanded) {
+ animateNotificationPanel(DEFAULT_FLING_VELOCITY, true);
+ }
+ return true;
}
@Override
@@ -1109,7 +1161,9 @@
@Override
public boolean onSingleTapUp(MotionEvent e) {
mClosingVelocity = DEFAULT_FLING_VELOCITY;
- close();
+ if (mPanelExpanded) {
+ close();
+ }
return super.onSingleTapUp(e);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java
new file mode 100644
index 0000000..8de1439
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.car;
+
+import android.annotation.NonNull;
+import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.hardware.power.CarPowerManager;
+import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.util.Log;
+
+/**
+ * Helper class for connecting to the {@link CarPowerManager} and listening for power state changes.
+ */
+public class PowerManagerHelper {
+ public static final String TAG = "PowerManagerHelper";
+
+ private final Context mContext;
+ private final CarPowerStateListener mCarPowerStateListener;
+
+ private Car mCar;
+ private CarPowerManager mCarPowerManager;
+
+ private final ServiceConnection mCarConnectionListener =
+ new ServiceConnection() {
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ Log.d(TAG, "Car Service connected");
+ try {
+ mCarPowerManager = (CarPowerManager) mCar.getCarManager(Car.POWER_SERVICE);
+ if (mCarPowerManager != null) {
+ mCarPowerManager.setListener(mCarPowerStateListener);
+ } else {
+ Log.e(TAG, "CarPowerManager service not available");
+ }
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Car not connected", e);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ destroyCarPowerManager();
+ }
+ };
+
+ PowerManagerHelper(Context context, @NonNull CarPowerStateListener listener) {
+ mContext = context;
+ mCarPowerStateListener = listener;
+ }
+
+ /**
+ * Connect to Car service.
+ */
+ void connectToCarService() {
+ mCar = Car.createCar(mContext, mCarConnectionListener);
+ if (mCar != null) {
+ mCar.connect();
+ }
+ }
+
+ /**
+ * Disconnects from Car service.
+ */
+ void disconnectFromCarService() {
+ if (mCar != null) {
+ mCar.disconnect();
+ }
+ }
+
+ private void destroyCarPowerManager() {
+ if (mCarPowerManager != null) {
+ mCarPowerManager.clearListener();
+ }
+ }
+}
diff --git a/packages/DefaultContainerService/Android.bp b/packages/DefaultContainerService/Android.bp
deleted file mode 100644
index d4ba6e8..0000000
--- a/packages/DefaultContainerService/Android.bp
+++ /dev/null
@@ -1,8 +0,0 @@
-android_app {
- name: "DefaultContainerService",
- srcs: ["**/*.java"],
- platform_apis: true,
- jni_libs: ["libdefcontainer_jni"],
- certificate: "platform",
- privileged: true,
-}
diff --git a/packages/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml
deleted file mode 100644
index 9f54652..0000000
--- a/packages/DefaultContainerService/AndroidManifest.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.defcontainer" coreApp="true">
- <uses-permission android:name="android.permission.ALLOCATE_AGGRESSIVE"/>
- <uses-permission android:name="android.permission.ASEC_ACCESS"/>
- <uses-permission android:name="android.permission.ASEC_CREATE"/>
- <uses-permission android:name="android.permission.ASEC_DESTROY"/>
- <uses-permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"/>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
-
- <application android:label="@string/service_name"
- android:allowBackup="false"
- android:defaultToDeviceProtectedStorage="true"
- android:directBootAware="true">
-
- <service android:name=".DefaultContainerService"
- android:enabled="true"
- android:exported="true"
- android:permission="android.permission.COPY_PROTECTED_DATA"/>
- </application>
-
-</manifest>
diff --git a/packages/DefaultContainerService/jni/Android.bp b/packages/DefaultContainerService/jni/Android.bp
deleted file mode 100644
index 7d7b095..0000000
--- a/packages/DefaultContainerService/jni/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-cc_library_shared {
- name: "libdefcontainer_jni",
-
- srcs: ["com_android_defcontainer_MeasurementUtils.cpp"],
-
- shared_libs: [
- "libnativehelper",
- "libutils",
- "liblog",
- ],
-
- static_libs: ["libdiskusage"],
-
- cflags: [
- "-Wall",
- "-Werror",
- "-Wunused",
- "-Wunreachable-code",
- ],
-}
diff --git a/packages/DefaultContainerService/jni/com_android_defcontainer_MeasurementUtils.cpp b/packages/DefaultContainerService/jni/com_android_defcontainer_MeasurementUtils.cpp
deleted file mode 100644
index 53cdc9d..0000000
--- a/packages/DefaultContainerService/jni/com_android_defcontainer_MeasurementUtils.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "DefContainer-JNI"
-
-#include <nativehelper/JNIHelp.h>
-
-#include <diskusage/dirsize.h>
-#include <utils/Log.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-
-namespace android {
-
-static jlong native_measureDirectory(JNIEnv* env, jobject /* clazz */, jstring directory) {
- jlong ret = 0L;
-
- const char* path = env->GetStringUTFChars(directory, NULL);
- if (path == NULL) {
- return ret;
- }
-
- int dirfd = open(path, O_DIRECTORY, O_RDONLY);
- if (dirfd < 0) {
- ALOGI("error opening: %s: %s", path, strerror(errno));
- } else {
- ret = calculate_dir_size(dirfd);
- close(dirfd);
- }
-
- env->ReleaseStringUTFChars(directory, path);
-
- return ret;
-}
-
-static const JNINativeMethod g_methods[] = {
- { "native_measureDirectory", "(Ljava/lang/String;)J", (void*)native_measureDirectory },
-};
-
-int register_com_android_defcontainer(JNIEnv *env) {
- if (jniRegisterNativeMethods(
- env, "com/android/defcontainer/MeasurementUtils", g_methods, NELEM(g_methods)) < 0) {
- return JNI_ERR;
- }
-
- return JNI_VERSION_1_6;
-}
-
-} // namespace android
-
-int JNI_OnLoad(JavaVM *jvm, void* /* reserved */) {
- JNIEnv *env;
-
- if (jvm->GetEnv((void**)&env, JNI_VERSION_1_6)) {
- return JNI_ERR;
- }
-
- return android::register_com_android_defcontainer(env);
-}
diff --git a/packages/DefaultContainerService/res/values-af/strings.xml b/packages/DefaultContainerService/res/values-af/strings.xml
deleted file mode 100644
index 5fa075b..0000000
--- a/packages/DefaultContainerService/res/values-af/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Pakkettoegangshelper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-am/strings.xml b/packages/DefaultContainerService/res/values-am/strings.xml
deleted file mode 100644
index 1101a45..0000000
--- a/packages/DefaultContainerService/res/values-am/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"ጥቅል ድረስ አጋዥ"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ar/strings.xml b/packages/DefaultContainerService/res/values-ar/strings.xml
deleted file mode 100644
index 823e472..0000000
--- a/packages/DefaultContainerService/res/values-ar/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"مساعد الدخول إلى الحزمة"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-as/strings.xml b/packages/DefaultContainerService/res/values-as/strings.xml
deleted file mode 100644
index 1b6391c..0000000
--- a/packages/DefaultContainerService/res/values-as/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"পেকেজ চোৱা সহায়ক"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-az/strings.xml b/packages/DefaultContainerService/res/values-az/strings.xml
deleted file mode 100644
index cae7d02..0000000
--- a/packages/DefaultContainerService/res/values-az/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Paket Giriş Yardımçısı"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-b+sr+Latn/strings.xml b/packages/DefaultContainerService/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index a0e1734..0000000
--- a/packages/DefaultContainerService/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Pomoćnik za pristup paketu"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-be/strings.xml b/packages/DefaultContainerService/res/values-be/strings.xml
deleted file mode 100644
index 68621b6..0000000
--- a/packages/DefaultContainerService/res/values-be/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Памочнік дост. да пакетаў"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-bg/strings.xml b/packages/DefaultContainerService/res/values-bg/strings.xml
deleted file mode 100644
index 7f8939a..0000000
--- a/packages/DefaultContainerService/res/values-bg/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Помощ в достъпа до пакети"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-bn/strings.xml b/packages/DefaultContainerService/res/values-bn/strings.xml
deleted file mode 100644
index 23b197f..0000000
--- a/packages/DefaultContainerService/res/values-bn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"প্যাকেজ অ্যাক্সেস সাহায়ক"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-bs/strings.xml b/packages/DefaultContainerService/res/values-bs/strings.xml
deleted file mode 100644
index 9be3873..0000000
--- a/packages/DefaultContainerService/res/values-bs/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Asistent pristupa paketu"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ca/strings.xml b/packages/DefaultContainerService/res/values-ca/strings.xml
deleted file mode 100644
index e19c72c..0000000
--- a/packages/DefaultContainerService/res/values-ca/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Assist. d\'accés a paquets"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-cs/strings.xml b/packages/DefaultContainerService/res/values-cs/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-cs/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-da/strings.xml b/packages/DefaultContainerService/res/values-da/strings.xml
deleted file mode 100644
index 5243028..0000000
--- a/packages/DefaultContainerService/res/values-da/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Hjælp til pakkeadgang"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-de/strings.xml b/packages/DefaultContainerService/res/values-de/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-de/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-el/strings.xml b/packages/DefaultContainerService/res/values-el/strings.xml
deleted file mode 100644
index a4d8144..0000000
--- a/packages/DefaultContainerService/res/values-el/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Βοηθός πρόσβασης πακέτου"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-en-rAU/strings.xml b/packages/DefaultContainerService/res/values-en-rAU/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-en-rCA/strings.xml b/packages/DefaultContainerService/res/values-en-rCA/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-en-rGB/strings.xml b/packages/DefaultContainerService/res/values-en-rGB/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-en-rIN/strings.xml b/packages/DefaultContainerService/res/values-en-rIN/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-en-rXC/strings.xml b/packages/DefaultContainerService/res/values-en-rXC/strings.xml
deleted file mode 100644
index 913f4bd..0000000
--- a/packages/DefaultContainerService/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-es-rUS/strings.xml b/packages/DefaultContainerService/res/values-es-rUS/strings.xml
deleted file mode 100644
index 19fd655..0000000
--- a/packages/DefaultContainerService/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Asist. acceso al paquete"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-es/strings.xml b/packages/DefaultContainerService/res/values-es/strings.xml
deleted file mode 100644
index 022c461..0000000
--- a/packages/DefaultContainerService/res/values-es/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Ayudante acceso a paquete"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-et/strings.xml b/packages/DefaultContainerService/res/values-et/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-et/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-eu/strings.xml b/packages/DefaultContainerService/res/values-eu/strings.xml
deleted file mode 100644
index 4df24e1..0000000
--- a/packages/DefaultContainerService/res/values-eu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Paketeak atzitzeko laguntzailea"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-fa/strings.xml b/packages/DefaultContainerService/res/values-fa/strings.xml
deleted file mode 100644
index 8c1a5d4..0000000
--- a/packages/DefaultContainerService/res/values-fa/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"راهنمای دسترسی به بسته"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-fi/strings.xml b/packages/DefaultContainerService/res/values-fi/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-fi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-fr-rCA/strings.xml b/packages/DefaultContainerService/res/values-fr-rCA/strings.xml
deleted file mode 100644
index 353d0b4..0000000
--- a/packages/DefaultContainerService/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Aide Accès au paquet"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-fr/strings.xml b/packages/DefaultContainerService/res/values-fr/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-fr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-gl/strings.xml b/packages/DefaultContainerService/res/values-gl/strings.xml
deleted file mode 100644
index c1ae018..0000000
--- a/packages/DefaultContainerService/res/values-gl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Asistente acceso paquetes"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-gu/strings.xml b/packages/DefaultContainerService/res/values-gu/strings.xml
deleted file mode 100644
index cbebdd2..0000000
--- a/packages/DefaultContainerService/res/values-gu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"પેકેજ અૅક્સેસ હેલ્પર"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-hi/strings.xml b/packages/DefaultContainerService/res/values-hi/strings.xml
deleted file mode 100644
index ad85379..0000000
--- a/packages/DefaultContainerService/res/values-hi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"पैकेज पहुंच सहायक"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-hr/strings.xml b/packages/DefaultContainerService/res/values-hr/strings.xml
deleted file mode 100644
index 56b7db1..0000000
--- a/packages/DefaultContainerService/res/values-hr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Pomoćnik pristupa paketu"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-hu/strings.xml b/packages/DefaultContainerService/res/values-hu/strings.xml
deleted file mode 100644
index 78ca9fa..0000000
--- a/packages/DefaultContainerService/res/values-hu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Csomaghozzáférés-segéd"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-hy/strings.xml b/packages/DefaultContainerService/res/values-hy/strings.xml
deleted file mode 100644
index 1e2f587..0000000
--- a/packages/DefaultContainerService/res/values-hy/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Փաթեթի մուտքի օժանդակող"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-in/strings.xml b/packages/DefaultContainerService/res/values-in/strings.xml
deleted file mode 100644
index da6bf8b..0000000
--- a/packages/DefaultContainerService/res/values-in/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Pembantu Akses Paket"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-is/strings.xml b/packages/DefaultContainerService/res/values-is/strings.xml
deleted file mode 100644
index 41ca827..0000000
--- a/packages/DefaultContainerService/res/values-is/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Pakkaaðgangshjálp"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-it/strings.xml b/packages/DefaultContainerService/res/values-it/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-it/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-iw/strings.xml b/packages/DefaultContainerService/res/values-iw/strings.xml
deleted file mode 100644
index 4a93179..0000000
--- a/packages/DefaultContainerService/res/values-iw/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"מסייע בגישה לחבילה"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ja/strings.xml b/packages/DefaultContainerService/res/values-ja/strings.xml
deleted file mode 100644
index 2f57e4e..0000000
--- a/packages/DefaultContainerService/res/values-ja/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"パッケージアクセス支援ツール"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ka/strings.xml b/packages/DefaultContainerService/res/values-ka/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-ka/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-kk/strings.xml b/packages/DefaultContainerService/res/values-kk/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-kk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-km/strings.xml b/packages/DefaultContainerService/res/values-km/strings.xml
deleted file mode 100644
index 1006d56..0000000
--- a/packages/DefaultContainerService/res/values-km/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"កម្មវិធីជំនួយចូលដំណើរការកញ្ចប់"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-kn/strings.xml b/packages/DefaultContainerService/res/values-kn/strings.xml
deleted file mode 100644
index 13af0cc..0000000
--- a/packages/DefaultContainerService/res/values-kn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"ಪ್ಯಾಕೇಜ್ ಪ್ರವೇಶದ ಸಹಾಯಕ"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ko/strings.xml b/packages/DefaultContainerService/res/values-ko/strings.xml
deleted file mode 100644
index 0304972..0000000
--- a/packages/DefaultContainerService/res/values-ko/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"패키지 액세스 도움말"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ky/strings.xml b/packages/DefaultContainerService/res/values-ky/strings.xml
deleted file mode 100644
index d91e67d..0000000
--- a/packages/DefaultContainerService/res/values-ky/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Топтомго уруксат берүү"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-lo/strings.xml b/packages/DefaultContainerService/res/values-lo/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-lo/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-lt/strings.xml b/packages/DefaultContainerService/res/values-lt/strings.xml
deleted file mode 100644
index 3faf8cc..0000000
--- a/packages/DefaultContainerService/res/values-lt/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Pak. pagalb. prm. prieiga"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-lv/strings.xml b/packages/DefaultContainerService/res/values-lv/strings.xml
deleted file mode 100644
index 63beee5..0000000
--- a/packages/DefaultContainerService/res/values-lv/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Pakotnes piekļuves palīgs"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-mk/strings.xml b/packages/DefaultContainerService/res/values-mk/strings.xml
deleted file mode 100644
index 875cc2f..0000000
--- a/packages/DefaultContainerService/res/values-mk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Помошник за пристап кон пакет"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ml/strings.xml b/packages/DefaultContainerService/res/values-ml/strings.xml
deleted file mode 100644
index 7bb450f..0000000
--- a/packages/DefaultContainerService/res/values-ml/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"പാക്കേജ് ആക്സസ്സ് സഹായി"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-mn/strings.xml b/packages/DefaultContainerService/res/values-mn/strings.xml
deleted file mode 100644
index d9fe647..0000000
--- a/packages/DefaultContainerService/res/values-mn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Багц хандалтын тусламж"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-mr/strings.xml b/packages/DefaultContainerService/res/values-mr/strings.xml
deleted file mode 100644
index 898a378..0000000
--- a/packages/DefaultContainerService/res/values-mr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"पॅकेज प्रवेश मदतनीस"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ms/strings.xml b/packages/DefaultContainerService/res/values-ms/strings.xml
deleted file mode 100644
index 77d7927..0000000
--- a/packages/DefaultContainerService/res/values-ms/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Pembantu Akses Pakej"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-my/strings.xml b/packages/DefaultContainerService/res/values-my/strings.xml
deleted file mode 100644
index 8dfb72b..0000000
--- a/packages/DefaultContainerService/res/values-my/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Packageအသုံးပြုကူညီသူ"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-nb/strings.xml b/packages/DefaultContainerService/res/values-nb/strings.xml
deleted file mode 100644
index 637f54d..0000000
--- a/packages/DefaultContainerService/res/values-nb/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Hjelpeprogram for pakketilgang"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ne/strings.xml b/packages/DefaultContainerService/res/values-ne/strings.xml
deleted file mode 100644
index 5b70ce1..0000000
--- a/packages/DefaultContainerService/res/values-ne/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"प्याकेज पहुँच सहयोगी"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-nl/strings.xml b/packages/DefaultContainerService/res/values-nl/strings.xml
deleted file mode 100644
index 2501099..0000000
--- a/packages/DefaultContainerService/res/values-nl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Helper pakkettoegang"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-or/strings.xml b/packages/DefaultContainerService/res/values-or/strings.xml
deleted file mode 100644
index 394c278..0000000
--- a/packages/DefaultContainerService/res/values-or/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"ପ୍ୟାକେଜ୍ ଆକ୍ସେସ୍ ସହାୟକ"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-pa/strings.xml b/packages/DefaultContainerService/res/values-pa/strings.xml
deleted file mode 100644
index a784a06..0000000
--- a/packages/DefaultContainerService/res/values-pa/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"ਪੈਕੇਜ ਪਹੁੰਚ ਸਹਾਇਕ"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-pl/strings.xml b/packages/DefaultContainerService/res/values-pl/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-pl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-pt-rBR/strings.xml b/packages/DefaultContainerService/res/values-pt-rBR/strings.xml
deleted file mode 100644
index 5fbd949..0000000
--- a/packages/DefaultContainerService/res/values-pt-rBR/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Assistente de pacote"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-pt-rPT/strings.xml b/packages/DefaultContainerService/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 647334b..0000000
--- a/packages/DefaultContainerService/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Ajuda acesso a pacotes"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-pt/strings.xml b/packages/DefaultContainerService/res/values-pt/strings.xml
deleted file mode 100644
index 5fbd949..0000000
--- a/packages/DefaultContainerService/res/values-pt/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Assistente de pacote"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ro/strings.xml b/packages/DefaultContainerService/res/values-ro/strings.xml
deleted file mode 100644
index 69de00f..0000000
--- a/packages/DefaultContainerService/res/values-ro/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Ajutor accesare pachet"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ru/strings.xml b/packages/DefaultContainerService/res/values-ru/strings.xml
deleted file mode 100644
index ccb0c53..0000000
--- a/packages/DefaultContainerService/res/values-ru/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Мастер доступа к пакетам"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-si/strings.xml b/packages/DefaultContainerService/res/values-si/strings.xml
deleted file mode 100644
index 522ec6c..0000000
--- a/packages/DefaultContainerService/res/values-si/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"පැකේජ ප්රවේශ උදව්කරු"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-sk/strings.xml b/packages/DefaultContainerService/res/values-sk/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-sk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-sl/strings.xml b/packages/DefaultContainerService/res/values-sl/strings.xml
deleted file mode 100644
index af2b13c..0000000
--- a/packages/DefaultContainerService/res/values-sl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Pomočnik za dostop do paketa"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-sq/strings.xml b/packages/DefaultContainerService/res/values-sq/strings.xml
deleted file mode 100644
index d352edf..0000000
--- a/packages/DefaultContainerService/res/values-sq/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Ndihmësi i qasjes në paketë"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-sr/strings.xml b/packages/DefaultContainerService/res/values-sr/strings.xml
deleted file mode 100644
index b5d77ac..0000000
--- a/packages/DefaultContainerService/res/values-sr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Помоћник за приступ пакету"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-sv/strings.xml b/packages/DefaultContainerService/res/values-sv/strings.xml
deleted file mode 100644
index 097a709..0000000
--- a/packages/DefaultContainerService/res/values-sv/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Hjälp med paketåtkomst"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-sw/strings.xml b/packages/DefaultContainerService/res/values-sw/strings.xml
deleted file mode 100644
index 8d1f515..0000000
--- a/packages/DefaultContainerService/res/values-sw/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Kisaidizi cha Kufikia Furushi"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ta/strings.xml b/packages/DefaultContainerService/res/values-ta/strings.xml
deleted file mode 100644
index a7ba82d..0000000
--- a/packages/DefaultContainerService/res/values-ta/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"தொகுப்பு அணுகலுக்கான உதவி"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-te/strings.xml b/packages/DefaultContainerService/res/values-te/strings.xml
deleted file mode 100644
index 5be53e5..0000000
--- a/packages/DefaultContainerService/res/values-te/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"ప్యాకేజీ యాక్సెస్ సహాయకం"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-th/strings.xml b/packages/DefaultContainerService/res/values-th/strings.xml
deleted file mode 100644
index 621d7ed..0000000
--- a/packages/DefaultContainerService/res/values-th/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"ตัวช่วยเหลือของการเข้าถึงแพ็กเกจ"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-tl/strings.xml b/packages/DefaultContainerService/res/values-tl/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-tl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-tr/strings.xml b/packages/DefaultContainerService/res/values-tr/strings.xml
deleted file mode 100644
index 12ea674..0000000
--- a/packages/DefaultContainerService/res/values-tr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Paket Erişim Yardımcısı"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-uk/strings.xml b/packages/DefaultContainerService/res/values-uk/strings.xml
deleted file mode 100644
index 1226bd4..0000000
--- a/packages/DefaultContainerService/res/values-uk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Майстер доступу до пакетів"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-ur/strings.xml b/packages/DefaultContainerService/res/values-ur/strings.xml
deleted file mode 100644
index 3872b86..0000000
--- a/packages/DefaultContainerService/res/values-ur/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"پیکیج رسائی کا مددگار"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-uz/strings.xml b/packages/DefaultContainerService/res/values-uz/strings.xml
deleted file mode 100644
index 216d715..0000000
--- a/packages/DefaultContainerService/res/values-uz/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-vi/strings.xml b/packages/DefaultContainerService/res/values-vi/strings.xml
deleted file mode 100644
index 885946c..0000000
--- a/packages/DefaultContainerService/res/values-vi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Trình trợ giúp truy cập gói"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-zh-rCN/strings.xml b/packages/DefaultContainerService/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 2bcc6b7..0000000
--- a/packages/DefaultContainerService/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"软件包权限帮助程序"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-zh-rHK/strings.xml b/packages/DefaultContainerService/res/values-zh-rHK/strings.xml
deleted file mode 100644
index 9a43509..0000000
--- a/packages/DefaultContainerService/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"套件存取輔助程式"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-zh-rTW/strings.xml b/packages/DefaultContainerService/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 9a43509..0000000
--- a/packages/DefaultContainerService/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"套件存取輔助程式"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values-zu/strings.xml b/packages/DefaultContainerService/res/values-zu/strings.xml
deleted file mode 100644
index d501165..0000000
--- a/packages/DefaultContainerService/res/values-zu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="service_name" msgid="4841491635055379553">"Umsizi Wokufinyelela Kwiphakheji"</string>
-</resources>
diff --git a/packages/DefaultContainerService/res/values/strings.xml b/packages/DefaultContainerService/res/values/strings.xml
deleted file mode 100644
index ffd6b59..0000000
--- a/packages/DefaultContainerService/res/values/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- service name [CHAR LIMIT=25] -->
- <string name="service_name">Package Access Helper</string>
-</resources>
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
deleted file mode 100644
index 97a67c2..0000000
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.defcontainer;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageInfoLite;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.PackageLite;
-import android.content.pm.PackageParser.PackageParserException;
-import android.content.res.ObbInfo;
-import android.content.res.ObbScanner;
-import android.os.Binder;
-import android.os.FileUtils;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.internal.app.IMediaContainerService;
-import com.android.internal.content.PackageHelper;
-import com.android.internal.os.IParcelFileDescriptorFactory;
-import com.android.internal.util.ArrayUtils;
-
-import libcore.io.IoUtils;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Service that offers to inspect and copy files that may reside on removable
- * storage. This is designed to prevent the system process from holding onto
- * open files that cause the kernel to kill it when the underlying device is
- * removed.
- */
-public class DefaultContainerService extends Service {
- private static final String TAG = "DefContainer";
-
- // TODO: migrate native code unpacking to always be a derivative work
-
- private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {
- /**
- * Copy package to the target location.
- *
- * @param packagePath absolute path to the package to be copied. Can be
- * a single monolithic APK file or a cluster directory
- * containing one or more APKs.
- * @return returns status code according to those in
- * {@link PackageManager}
- */
- @Override
- public int copyPackage(String packagePath, IParcelFileDescriptorFactory target) {
- if (packagePath == null || target == null) {
- return PackageManager.INSTALL_FAILED_INVALID_URI;
- }
-
- PackageLite pkg = null;
- try {
- final File packageFile = new File(packagePath);
- pkg = PackageParser.parsePackageLite(packageFile, 0);
- return copyPackageInner(pkg, target);
- } catch (PackageParserException | IOException | RemoteException e) {
- Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e);
- return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- }
- }
-
- /**
- * Parse given package and return minimal details.
- *
- * @param packagePath absolute path to the package to be copied. Can be
- * a single monolithic APK file or a cluster directory
- * containing one or more APKs.
- */
- @Override
- public PackageInfoLite getMinimalPackageInfo(String packagePath, int flags,
- String abiOverride) {
- final Context context = DefaultContainerService.this;
-
- PackageInfoLite ret = new PackageInfoLite();
- if (packagePath == null) {
- Slog.i(TAG, "Invalid package file " + packagePath);
- ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
- return ret;
- }
-
- final File packageFile = new File(packagePath);
- final PackageParser.PackageLite pkg;
- final long sizeBytes;
- try {
- pkg = PackageParser.parsePackageLite(packageFile, 0);
- sizeBytes = PackageHelper.calculateInstalledSize(pkg, abiOverride);
- } catch (PackageParserException | IOException e) {
- Slog.w(TAG, "Failed to parse package at " + packagePath + ": " + e);
-
- if (!packageFile.exists()) {
- ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_URI;
- } else {
- ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
- }
-
- return ret;
- }
-
- final int recommendedInstallLocation;
- final long token = Binder.clearCallingIdentity();
- try {
- recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
- pkg.packageName, pkg.installLocation, sizeBytes, flags);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
- ret.packageName = pkg.packageName;
- ret.splitNames = pkg.splitNames;
- ret.versionCode = pkg.versionCode;
- ret.versionCodeMajor = pkg.versionCodeMajor;
- ret.baseRevisionCode = pkg.baseRevisionCode;
- ret.splitRevisionCodes = pkg.splitRevisionCodes;
- ret.installLocation = pkg.installLocation;
- ret.verifiers = pkg.verifiers;
- ret.recommendedInstallLocation = recommendedInstallLocation;
- ret.multiArch = pkg.multiArch;
-
- return ret;
- }
-
- @Override
- public ObbInfo getObbInfo(String filename) {
- try {
- return ObbScanner.getObbInfo(filename);
- } catch (IOException e) {
- Slog.d(TAG, "Couldn't get OBB info for " + filename);
- return null;
- }
- }
-
- /**
- * Calculate estimated footprint of given package post-installation.
- *
- * @param packagePath absolute path to the package to be copied. Can be
- * a single monolithic APK file or a cluster directory
- * containing one or more APKs.
- */
- @Override
- public long calculateInstalledSize(String packagePath, String abiOverride)
- throws RemoteException {
- final File packageFile = new File(packagePath);
- final PackageParser.PackageLite pkg;
- try {
- pkg = PackageParser.parsePackageLite(packageFile, 0);
- return PackageHelper.calculateInstalledSize(pkg, abiOverride);
- } catch (PackageParserException | IOException e) {
- Slog.w(TAG, "Failed to calculate installed size: " + e);
- return Long.MAX_VALUE;
- }
- }
- };
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target)
- throws IOException, RemoteException {
- copyFile(pkg.baseCodePath, target, "base.apk");
- if (!ArrayUtils.isEmpty(pkg.splitNames)) {
- for (int i = 0; i < pkg.splitNames.length; i++) {
- copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk");
- }
- }
-
- return PackageManager.INSTALL_SUCCEEDED;
- }
-
- private void copyFile(String sourcePath, IParcelFileDescriptorFactory target, String targetName)
- throws IOException, RemoteException {
- Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);
- InputStream in = null;
- OutputStream out = null;
- try {
- in = new FileInputStream(sourcePath);
- out = new ParcelFileDescriptor.AutoCloseOutputStream(
- target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE));
- FileUtils.copy(in, out);
- } finally {
- IoUtils.closeQuietly(out);
- IoUtils.closeQuietly(in);
- }
- }
-}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/MeasurementUtils.java b/packages/DefaultContainerService/src/com/android/defcontainer/MeasurementUtils.java
deleted file mode 100644
index 6f5f53b..0000000
--- a/packages/DefaultContainerService/src/com/android/defcontainer/MeasurementUtils.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.defcontainer;
-
-public class MeasurementUtils {
- static {
- System.loadLibrary("defcontainer_jni");
- }
-
- public static long measureDirectory(String path) {
- return native_measureDirectory(path);
- }
-
- private native static long native_measureDirectory(String path);
-}
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index 73bfd30..8592fc9 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -17,7 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="android.ext.services"
- android:versionCode="210000000"
+ android:versionCode="220000000"
android:versionName="1"
coreApp="true">
diff --git a/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java b/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
index 6a47901..1962571 100644
--- a/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
+++ b/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
@@ -83,7 +83,7 @@
* the edit distance is at least as big as the {@code max} parameter
*/
// Note: copied verbatim from com.android.tools.lint.detector.api.LintUtils.java
- private static int editDistance(@NonNull String s, @NonNull String t, int max) {
+ public static int editDistance(@NonNull String s, @NonNull String t, int max) {
if (s.equals(t)) {
return 0;
}
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index b2baff5..73c7895 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.ActivityThread;
import android.app.INotificationManager;
import android.app.Notification;
@@ -71,6 +72,7 @@
/**
* Notification assistant that provides guidance on notification channel blocking
*/
+@SuppressLint("OverrideAbstract")
public class Assistant extends NotificationAssistantService {
private static final String TAG = "ExtAssistant";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -238,7 +240,7 @@
}
mSingleThreadExecutor.submit(() -> {
NotificationEntry entry =
- new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
+ new NotificationEntry(getContext(), mPackageManager, sbn, channel, mSmsHelper);
SmartActionsHelper.SmartSuggestions suggestions = mSmartActionsHelper.suggest(entry);
if (DEBUG) {
Log.d(TAG, String.format(
@@ -295,7 +297,7 @@
}
Ranking ranking = getRanking(sbn.getKey(), rankingMap);
if (ranking != null && ranking.getChannel() != null) {
- NotificationEntry entry = new NotificationEntry(mPackageManager,
+ NotificationEntry entry = new NotificationEntry(getContext(), mPackageManager,
sbn, ranking.getChannel(), mSmsHelper);
String key = getKey(
sbn.getPackageName(), sbn.getUserId(), ranking.getChannel().getId());
diff --git a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
index 84a8a8c..1ffbac9 100644
--- a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
+++ b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
@@ -28,18 +28,23 @@
import android.app.Person;
import android.app.RemoteInput;
import android.content.ComponentName;
+import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.media.AudioSystem;
import android.os.Build;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
import android.util.Log;
+import android.util.SparseArray;
import java.util.ArrayList;
import java.util.Objects;
+import java.util.Set;
/**
* Holds data about notifications.
@@ -47,6 +52,10 @@
public class NotificationEntry {
static final String TAG = "NotificationEntry";
+ // Copied from hidden definitions in Notification.TvExtender
+ private static final String EXTRA_TV_EXTENDER = "android.tv.EXTENSIONS";
+
+ private final Context mContext;
private final StatusBarNotification mSbn;
private final IPackageManager mPackageManager;
private int mTargetSdkVersion = Build.VERSION_CODES.N_MR1;
@@ -60,9 +69,10 @@
private final Object mLock = new Object();
- public NotificationEntry(IPackageManager packageManager, StatusBarNotification sbn,
- NotificationChannel channel, SmsHelper smsHelper) {
- mSbn = sbn;
+ public NotificationEntry(Context applicationContext, IPackageManager packageManager,
+ StatusBarNotification sbn, NotificationChannel channel, SmsHelper smsHelper) {
+ mContext = applicationContext;
+ mSbn = cloneStatusBarNotificationLight(sbn);
mChannel = channel;
mPackageManager = packageManager;
mPreChannelsNotification = isPreChannelsNotification();
@@ -71,6 +81,66 @@
mSmsHelper = smsHelper;
}
+ /** Adapted from {@code Notification.lightenPayload}. */
+ @SuppressWarnings("nullness")
+ private static void lightenNotificationPayload(Notification notification) {
+ notification.tickerView = null;
+ notification.contentView = null;
+ notification.bigContentView = null;
+ notification.headsUpContentView = null;
+ notification.largeIcon = null;
+ if (notification.extras != null && !notification.extras.isEmpty()) {
+ final Set<String> keyset = notification.extras.keySet();
+ final int keysetSize = keyset.size();
+ final String[] keys = keyset.toArray(new String[keysetSize]);
+ for (int i = 0; i < keysetSize; i++) {
+ final String key = keys[i];
+ if (EXTRA_TV_EXTENDER.equals(key)
+ || Notification.EXTRA_MESSAGES.equals(key)
+ || Notification.EXTRA_MESSAGING_PERSON.equals(key)
+ || Notification.EXTRA_PEOPLE_LIST.equals(key)) {
+ continue;
+ }
+ final Object obj = notification.extras.get(key);
+ if (obj != null
+ && (obj instanceof Parcelable
+ || obj instanceof Parcelable[]
+ || obj instanceof SparseArray
+ || obj instanceof ArrayList)) {
+ notification.extras.remove(key);
+ }
+ }
+ }
+ }
+
+ /** An interpretation of {@code Notification.cloneInto} with heavy=false. */
+ private Notification cloneNotificationLight(Notification notification) {
+ // We can't just use clone() here because the only way to remove the icons is with the
+ // builder, which we can only create with a Context.
+ Notification lightNotification =
+ Notification.Builder.recoverBuilder(mContext, notification)
+ .setSmallIcon(0)
+ .setLargeIcon((Icon) null)
+ .build();
+ lightenNotificationPayload(lightNotification);
+ return lightNotification;
+ }
+
+ /** Adapted from {@code StatusBarNotification.cloneLight}. */
+ public StatusBarNotification cloneStatusBarNotificationLight(StatusBarNotification sbn) {
+ return new StatusBarNotification(
+ sbn.getPackageName(),
+ sbn.getOpPkg(),
+ sbn.getId(),
+ sbn.getTag(),
+ sbn.getUid(),
+ /*initialPid=*/ 0,
+ /*score=*/ 0,
+ cloneNotificationLight(sbn.getNotification()),
+ sbn.getUser(),
+ sbn.getPostTime());
+ }
+
private boolean isPreChannelsNotification() {
try {
ApplicationInfo info = mPackageManager.getApplicationInfo(
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index 10360a3..93c522e 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -77,15 +77,13 @@
new ConversationActions(Collections.emptyList(), null);
private Context mContext;
- private TextClassifier mTextClassifier;
+ private TextClassificationManager mTextClassificationManager;
private AssistantSettings mSettings;
private LruCache<String, Session> mSessionCache = new LruCache<>(MAX_RESULT_ID_TO_CACHE);
SmartActionsHelper(Context context, AssistantSettings settings) {
mContext = context;
- TextClassificationManager textClassificationManager =
- mContext.getSystemService(TextClassificationManager.class);
- mTextClassifier = textClassificationManager.getTextClassifier();
+ mTextClassificationManager = mContext.getSystemService(TextClassificationManager.class);
mSettings = settings;
}
@@ -244,7 +242,7 @@
.map(ConversationAction::getType)
.toArray(String[]::new))
.build();
- mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+ getTextClassifier().onTextClassifierEvent(textClassifierEvent);
}
/**
@@ -286,7 +284,7 @@
.setTypeConfig(typeConfigBuilder.build())
.build();
ConversationActions conversationActions =
- mTextClassifier.suggestConversationActions(request);
+ getTextClassifier().suggestConversationActions(request);
reportActionsGenerated(
conversationActions.getId(), conversationActions.getConversationActions());
return conversationActions;
@@ -310,7 +308,7 @@
TextClassifierEvent.TYPE_ACTIONS_SHOWN, session.resultId)
.build();
// TODO: If possible, report which replies / actions are actually seen by user.
- mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+ getTextClassifier().onTextClassifierEvent(textClassifierEvent);
}
void onNotificationDirectReplied(String key) {
@@ -322,7 +320,7 @@
createTextClassifierEventBuilder(
TextClassifierEvent.TYPE_MANUAL_REPLY, session.resultId)
.build();
- mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+ getTextClassifier().onTextClassifierEvent(textClassifierEvent);
}
void onSuggestedReplySent(String key, CharSequence reply,
@@ -340,7 +338,7 @@
.setEntityTypes(ConversationAction.TYPE_TEXT_REPLY)
.setScores(session.repliesScores.getOrDefault(reply, 0f))
.build();
- mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+ getTextClassifier().onTextClassifierEvent(textClassifierEvent);
}
void onActionClicked(String key, Notification.Action action,
@@ -361,7 +359,7 @@
TextClassifierEvent.TYPE_SMART_ACTION, session.resultId)
.setEntityTypes(actionType)
.build();
- mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+ getTextClassifier().onTextClassifierEvent(textClassifierEvent);
}
private Notification.Action createNotificationActionFromRemoteAction(
@@ -471,6 +469,10 @@
return new ArrayList<>(extractMessages);
}
+ private TextClassifier getTextClassifier() {
+ return mTextClassificationManager.getTextClassifier();
+ }
+
private static boolean arePersonsEqual(Person left, Person right) {
return Objects.equals(left.getKey(), right.getKey())
&& Objects.equals(left.getName(), right.getName())
diff --git a/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java b/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
index 9b9d4be..3d754f7 100644
--- a/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
@@ -16,6 +16,7 @@
package android.ext.services.autofill;
import static android.ext.services.autofill.EditDistanceScorer.calculateScore;
+import static android.ext.services.autofill.EditDistanceScorer.editDistance;
import static com.google.common.truth.Truth.assertThat;
@@ -73,9 +74,12 @@
assertFloat(calculateScore(AutofillValue.forText("DUDx"), "Dude"), 0.75F);
}
+ @Test
+ public void testEditDistance_maxDistance() {
+ assertFloat(editDistance("testing", "b", 4), Integer.MAX_VALUE);
+ }
+
public static void assertFloat(float actualValue, float expectedValue) {
assertThat(actualValue).isWithin(0.01F).of(expectedValue);
}
-
-
}
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AgingHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AgingHelperTest.java
index 3db275a..a87d57c 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/AgingHelperTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/AgingHelperTest.java
@@ -102,7 +102,8 @@
public void testNoSnoozingOnPost() {
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
StatusBarNotification sbn = generateSbn(channel.getId());
- NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, sbn, channel, mSmsHelper);
mAgingHelper.onNotificationPosted(entry);
@@ -113,7 +114,8 @@
public void testPostResetsSnooze() {
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
StatusBarNotification sbn = generateSbn(channel.getId());
- NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, sbn, channel, mSmsHelper);
mAgingHelper.onNotificationPosted(entry);
@@ -124,7 +126,8 @@
public void testSnoozingOnSeen() {
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
StatusBarNotification sbn = generateSbn(channel.getId());
- NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, sbn, channel, mSmsHelper);
entry.setSeen();
when(mCategorizer.getCategory(entry)).thenReturn(NotificationCategorizer.CATEGORY_PEOPLE);
@@ -137,7 +140,8 @@
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
StatusBarNotification sbn = generateSbn(channel.getId());
- NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, sbn, channel, mSmsHelper);
when(mCategorizer.getCategory(entry)).thenReturn(NotificationCategorizer.CATEGORY_PEOPLE);
mAgingHelper.onNotificationSeen(entry);
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
index ee29bc5..012dcc0 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
@@ -468,8 +468,10 @@
@Test
public void testAssistantNeverIncreasesImportanceWhenSuggestingSilent() throws Exception {
StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C3, "min notif!", null);
- Adjustment adjust = mAssistant.createEnqueuedNotificationAdjustment(new NotificationEntry(
- mPackageManager, sbn, P1C3, mSmsHelper), new ArrayList<>(), new ArrayList<>());
+ Adjustment adjust = mAssistant.createEnqueuedNotificationAdjustment(
+ new NotificationEntry(mContext, mPackageManager, sbn, P1C3, mSmsHelper),
+ new ArrayList<>(),
+ new ArrayList<>());
assertEquals(IMPORTANCE_MIN, adjust.getSignals().getInt(Adjustment.KEY_IMPORTANCE));
}
}
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/NotificationEntryTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/NotificationEntryTest.java
index f51e911..c026079 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/NotificationEntryTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/NotificationEntryTest.java
@@ -24,6 +24,7 @@
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
@@ -34,6 +35,8 @@
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.os.Build;
import android.os.Process;
@@ -41,9 +44,6 @@
import android.service.notification.StatusBarNotification;
import android.testing.TestableContext;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -53,6 +53,9 @@
import java.util.ArrayList;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
@RunWith(AndroidJUnit4.class)
public class NotificationEntryTest {
private String mPkg = "pkg";
@@ -113,7 +116,8 @@
people.add(new Person.Builder().setKey("mailto:testing@android.com").build());
sbn.getNotification().extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, people);
- NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, sbn, channel, mSmsHelper);
assertTrue(entry.involvesPeople());
}
@@ -121,7 +125,8 @@
public void testNotPerson() {
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
StatusBarNotification sbn = generateSbn(channel.getId());
- NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, sbn, channel, mSmsHelper);
assertFalse(entry.involvesPeople());
}
@@ -129,7 +134,8 @@
public void testHasPerson_matchesDefaultSmsApp() {
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
StatusBarNotification sbn = generateSbn(channel.getId(), DEFAULT_SMS_PACKAGE_NAME);
- NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, sbn, channel, mSmsHelper);
assertTrue(entry.involvesPeople());
}
@@ -137,7 +143,8 @@
public void testHasPerson_doesntMatchDefaultSmsApp() {
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
StatusBarNotification sbn = generateSbn(channel.getId(), "abc");
- NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, sbn, channel, mSmsHelper);
assertFalse(entry.involvesPeople());
}
@@ -148,8 +155,8 @@
Notification n = new Notification.Builder(mContext, channel.getId())
.setStyle(new Notification.InboxStyle())
.build();
- NotificationEntry entry =
- new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
assertTrue(entry.hasStyle(Notification.InboxStyle.class));
}
@@ -160,8 +167,8 @@
Notification n = new Notification.Builder(mContext, channel.getId())
.setStyle(new Notification.MessagingStyle(""))
.build();
- NotificationEntry entry =
- new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
assertTrue(entry.hasStyle(Notification.MessagingStyle.class));
}
@@ -172,8 +179,8 @@
Notification n = new Notification.Builder(mContext, channel.getId())
.setStyle(new Notification.BigPictureStyle())
.build();
- NotificationEntry entry =
- new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
assertFalse(entry.hasStyle(Notification.InboxStyle.class));
assertFalse(entry.hasStyle(Notification.MessagingStyle.class));
}
@@ -184,7 +191,7 @@
channel.setSound(null, new AudioAttributes.Builder().setUsage(USAGE_ALARM).build());
NotificationEntry entry = new NotificationEntry(
- mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);
+ mContext, mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);
assertTrue(entry.isAudioAttributesUsage(USAGE_ALARM));
}
@@ -193,7 +200,7 @@
public void testIsNotAudioAttributes() {
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
NotificationEntry entry = new NotificationEntry(
- mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);
+ mContext, mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);
assertFalse(entry.isAudioAttributesUsage(USAGE_ALARM));
}
@@ -205,8 +212,8 @@
Notification n = new Notification.Builder(mContext, channel.getId())
.setCategory(Notification.CATEGORY_EMAIL)
.build();
- NotificationEntry entry =
- new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
assertTrue(entry.isCategory(Notification.CATEGORY_EMAIL));
assertFalse(entry.isCategory(Notification.CATEGORY_MESSAGE));
@@ -219,8 +226,8 @@
Notification n = new Notification.Builder(mContext, channel.getId())
.setFlag(FLAG_FOREGROUND_SERVICE, true)
.build();
- NotificationEntry entry =
- new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
assertTrue(entry.isOngoing());
}
@@ -232,9 +239,28 @@
Notification n = new Notification.Builder(mContext, channel.getId())
.setFlag(FLAG_CAN_COLORIZE, true)
.build();
- NotificationEntry entry =
- new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
assertFalse(entry.isOngoing());
}
+
+ @Test
+ public void testShrinkNotification() {
+ Notification n = new Notification.Builder(mContext, "")
+ .setLargeIcon(Icon.createWithResource(
+ mContext, android.R.drawable.alert_dark_frame))
+ .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .build();
+ n.largeIcon = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
+ NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+
+ NotificationEntry entry = new NotificationEntry(
+ mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
+
+ assertNull(entry.getNotification().getSmallIcon());
+ assertNull(entry.getNotification().getLargeIcon());
+ assertNull(entry.getNotification().largeIcon);
+ assertNull(entry.getNotification().extras.getParcelable(Notification.EXTRA_LARGE_ICON));
+ }
}
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
index dfa1ea0..69abe87 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
@@ -46,9 +46,6 @@
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextClassifierEvent;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
import com.google.common.truth.FailureStrategy;
import com.google.common.truth.Subject;
import com.google.common.truth.SubjectFactory;
@@ -71,9 +68,11 @@
import javax.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
@RunWith(AndroidJUnit4.class)
public class SmartActionsHelperTest {
- private static final String NOTIFICATION_KEY = "key";
private static final String RESULT_ID = "id";
private static final float SCORE = 0.7f;
private static final CharSequence SMART_REPLY = "Home";
@@ -88,7 +87,6 @@
IPackageManager mIPackageManager;
@Mock
private TextClassifier mTextClassifier;
- @Mock
private StatusBarNotification mStatusBarNotification;
@Mock
private SmsHelper mSmsHelper;
@@ -108,9 +106,6 @@
when(mTextClassifier.suggestConversationActions(any(ConversationActions.Request.class)))
.thenReturn(new ConversationActions(Arrays.asList(REPLY_ACTION), RESULT_ID));
- when(mStatusBarNotification.getPackageName()).thenReturn("random.app");
- when(mStatusBarNotification.getUser()).thenReturn(Process.myUserHandle());
- when(mStatusBarNotification.getKey()).thenReturn(NOTIFICATION_KEY);
mNotificationBuilder = new Notification.Builder(mContext, "channel");
mSettings = AssistantSettings.createForTesting(
null, null, Process.myUserHandle().getIdentifier(), null);
@@ -119,10 +114,15 @@
mSmartActionsHelper = new SmartActionsHelper(mContext, mSettings);
}
+ private void setStatusBarNotification(Notification n) {
+ mStatusBarNotification = new StatusBarNotification("random.app", "random.app", 0,
+ "tag", Process.myUid(), Process.myPid(), n, Process.myUserHandle(), null, 0);
+ }
+
@Test
public void testSuggest_notMessageNotification() {
Notification notification = mNotificationBuilder.setContentText(MESSAGE).build();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
@@ -137,7 +137,7 @@
.setContentText(MESSAGE)
.setCategory(Notification.CATEGORY_MESSAGE)
.build();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
ConversationActions.Request request = runSuggestAndCaptureRequest();
@@ -154,7 +154,7 @@
mSettings.mGenerateActions = false;
mSettings.mGenerateReplies = false;
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
@@ -167,7 +167,7 @@
mSettings.mGenerateReplies = true;
mSettings.mGenerateActions = false;
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
ConversationActions.Request request = runSuggestAndCaptureRequest();
@@ -184,7 +184,7 @@
mSettings.mGenerateReplies = false;
mSettings.mGenerateActions = true;
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
ConversationActions.Request request = runSuggestAndCaptureRequest();
@@ -200,7 +200,7 @@
@Test
public void testSuggest_nonMessageStyleMessageNotification() {
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
List<ConversationActions.Message> messages =
runSuggestAndCaptureRequest().getConversation();
@@ -233,7 +233,7 @@
.setStyle(style)
.setActions(createReplyAction())
.build();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
List<ConversationActions.Message> messages =
runSuggestAndCaptureRequest().getConversation();
@@ -288,7 +288,7 @@
.setStyle(style)
.setActions(createReplyAction())
.build();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
@@ -307,7 +307,7 @@
.setStyle(style)
.setActions(createReplyAction())
.build();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
@@ -318,11 +318,11 @@
@Test
public void testOnSuggestedReplySent() {
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
- mSmartActionsHelper.onSuggestedReplySent(
- NOTIFICATION_KEY, SMART_REPLY, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
+ mSmartActionsHelper.onSuggestedReplySent(mStatusBarNotification.getKey(), SMART_REPLY,
+ NotificationAssistantService.SOURCE_FROM_ASSISTANT);
ArgumentCaptor<TextClassifierEvent> argumentCaptor =
ArgumentCaptor.forClass(TextClassifierEvent.class);
@@ -338,7 +338,7 @@
@Test
public void testOnSuggestedReplySent_anotherNotification() {
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
mSmartActionsHelper.onSuggestedReplySent(
@@ -353,11 +353,11 @@
when(mTextClassifier.suggestConversationActions(any(ConversationActions.Request.class)))
.thenReturn(new ConversationActions(Collections.singletonList(REPLY_ACTION), null));
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
- mSmartActionsHelper.onSuggestedReplySent(
- NOTIFICATION_KEY, SMART_REPLY, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
+ mSmartActionsHelper.onSuggestedReplySent(mStatusBarNotification.getKey(), SMART_REPLY,
+ NotificationAssistantService.SOURCE_FROM_ASSISTANT);
verify(mTextClassifier, never()).onTextClassifierEvent(any(TextClassifierEvent.class));
}
@@ -365,10 +365,10 @@
@Test
public void testOnNotificationDirectReply() {
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
- mSmartActionsHelper.onNotificationDirectReplied(NOTIFICATION_KEY);
+ mSmartActionsHelper.onNotificationDirectReplied(mStatusBarNotification.getKey());
ArgumentCaptor<TextClassifierEvent> argumentCaptor =
ArgumentCaptor.forClass(TextClassifierEvent.class);
@@ -381,7 +381,7 @@
@Test
public void testOnNotificationExpansionChanged() {
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
mSmartActionsHelper.onNotificationExpansionChanged(createNotificationEntry(), true);
@@ -397,7 +397,7 @@
@Test
public void testOnNotificationsSeen_notExpanded() {
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
mSmartActionsHelper.onNotificationExpansionChanged(createNotificationEntry(), false);
@@ -409,7 +409,7 @@
@Test
public void testOnNotifications_expanded() {
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
mSmartActionsHelper.onNotificationExpansionChanged(createNotificationEntry(), true);
@@ -438,7 +438,7 @@
Collections.singletonList(conversationAction), null));
Notification notification = createMessageNotification();
- when(mStatusBarNotification.getNotification()).thenReturn(notification);
+ setStatusBarNotification(notification);
SmartActionsHelper.SmartSuggestions suggestions =
mSmartActionsHelper.suggest(createNotificationEntry());
@@ -477,7 +477,8 @@
private NotificationEntry createNotificationEntry() {
NotificationChannel channel =
new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
- return new NotificationEntry(mIPackageManager, mStatusBarNotification, channel, mSmsHelper);
+ return new NotificationEntry(
+ mContext, mIPackageManager, mStatusBarNotification, channel, mSmsHelper);
}
private Notification createMessageNotification() {
diff --git a/packages/MtpDocumentsProvider/res/values-mr/strings.xml b/packages/MtpDocumentsProvider/res/values-mr/strings.xml
index d581e10..983112c 100644
--- a/packages/MtpDocumentsProvider/res/values-mr/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-mr/strings.xml
@@ -20,6 +20,6 @@
<string name="downloads_app_label" msgid="7120690641874849726">"डाउनलोड"</string>
<string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
<string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> मधून फायलींंमध्ये प्रवेश करत आहे"</string>
- <string name="error_busy_device" msgid="3997316850357386589">"दुसरे डिव्हाइस व्यस्त आहे. ते उपलब्ध होईपर्यंत तुम्ही फायली ट्रांसफर करू शकत नाही."</string>
+ <string name="error_busy_device" msgid="3997316850357386589">"दुसरे डिव्हाइस व्यस्त आहे. ते उपलब्ध होईपर्यंत तुम्ही फायली ट्रान्सफर करू शकत नाही."</string>
<string name="error_locked_device" msgid="7557872102188356147">"कोणत्याही फायली आढळल्या नाहीत. दुसरे डिव्हाइस कदाचित बंद असू शकते. तसे असल्यास, ते अनलॉक करा आणि पुन्हा प्रयत्न करा."</string>
</resources>
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index 62de2ba..64718da 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -108,6 +108,8 @@
defaults: ["NetworkStackAppCommon"],
certificate: "platform",
manifest: "AndroidManifest_InProcess.xml",
+ // InProcessNetworkStack is a replacement for NetworkStack
+ overrides: ["NetworkStack"],
}
// Updatable network stack packaged as an application
@@ -116,6 +118,7 @@
defaults: ["NetworkStackAppCommon"],
certificate: "networkstack",
manifest: "AndroidManifest.xml",
+ use_embedded_native_libs: true,
}
genrule {
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index ac05c44..bfcd6c1 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -19,7 +19,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.networkstack"
android:sharedUserId="android.uid.networkstack"
- android:versionCode="210000000"
+ android:versionCode="220000000"
android:versionName="29 system image"
>
@@ -41,7 +41,7 @@
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<!-- Signature permission defined in NetworkStackStub -->
<uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
- <application>
+ <application android:extractNativeLibs="false">
<service android:name="com.android.server.NetworkStackService">
<intent-filter>
<action android:name="android.net.INetworkStackConnector"/>
diff --git a/packages/NetworkStack/AndroidManifestBase.xml b/packages/NetworkStack/AndroidManifestBase.xml
index d00a551..3da566f 100644
--- a/packages/NetworkStack/AndroidManifestBase.xml
+++ b/packages/NetworkStack/AndroidManifestBase.xml
@@ -24,6 +24,7 @@
android:label="NetworkStack"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true"
+ android:persistent="true"
android:usesCleartextTraffic="true">
<service android:name="com.android.server.connectivity.ipmemorystore.RegularMaintenanceJobService"
diff --git a/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java b/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java
index 475f826..41715b2 100644
--- a/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java
+++ b/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java
@@ -19,6 +19,9 @@
import android.annotation.NonNull;
import android.content.Context;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+
/**
* service used to communicate with the ip memory store service in network stack,
* which is running in the same module.
@@ -35,8 +38,7 @@
}
@Override
- @NonNull
- protected IIpMemoryStore getService() {
- return mService;
+ protected void runWhenServiceReady(Consumer<IIpMemoryStore> cb) throws ExecutionException {
+ cb.accept(mService);
}
}
diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java
index dc74c04..266b1b0 100644
--- a/packages/NetworkStack/src/android/net/ip/IpClient.java
+++ b/packages/NetworkStack/src/android/net/ip/IpClient.java
@@ -372,10 +372,6 @@
private boolean mMulticastFiltering;
private long mStartTimeMillis;
- /* This must match the definition in KeepaliveTracker.KeepaliveInfo */
- private static final int TYPE_NATT = 1;
- private static final int TYPE_TCP = 2;
-
/**
* Reading the snapshot is an asynchronous operation initiated by invoking
* Callback.startReadPacketFilter() and completed when the WiFi Service responds with an
@@ -705,7 +701,7 @@
* keepalive offload.
*/
public void addKeepalivePacketFilter(int slot, @NonNull TcpKeepalivePacketDataParcelable pkt) {
- sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, TYPE_TCP, pkt);
+ sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0 /* Unused */, pkt);
}
/**
@@ -714,7 +710,7 @@
*/
public void addNattKeepalivePacketFilter(int slot,
@NonNull NattKeepalivePacketDataParcelable pkt) {
- sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, TYPE_NATT, pkt);
+ sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0 /* Unused */ , pkt);
}
/**
@@ -1626,13 +1622,12 @@
case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: {
final int slot = msg.arg1;
- final int type = msg.arg2;
if (mApfFilter != null) {
- if (type == TYPE_NATT) {
+ if (msg.obj instanceof NattKeepalivePacketDataParcelable) {
mApfFilter.addNattKeepalivePacketFilter(slot,
(NattKeepalivePacketDataParcelable) msg.obj);
- } else {
+ } else if (msg.obj instanceof TcpKeepalivePacketDataParcelable) {
mApfFilter.addTcpKeepalivePacketFilter(slot,
(TcpKeepalivePacketDataParcelable) msg.obj);
}
diff --git a/packages/NetworkStack/src/com/android/networkstack/util/DnsUtils.java b/packages/NetworkStack/src/com/android/networkstack/util/DnsUtils.java
new file mode 100644
index 0000000..85f94e1
--- /dev/null
+++ b/packages/NetworkStack/src/com/android/networkstack/util/DnsUtils.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.networkstack.util;
+
+import static android.net.DnsResolver.FLAG_NO_CACHE_LOOKUP;
+import static android.net.DnsResolver.TYPE_A;
+import static android.net.DnsResolver.TYPE_AAAA;
+
+import android.annotation.NonNull;
+import android.net.DnsResolver;
+import android.net.Network;
+import android.net.TrafficStats;
+import android.util.Log;
+
+import com.android.internal.util.TrafficStatsConstants;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Collection of utilities for dns query.
+ */
+public class DnsUtils {
+ // Decide what queries to make depending on what IP addresses are on the system.
+ public static final int TYPE_ADDRCONFIG = -1;
+ private static final String TAG = DnsUtils.class.getSimpleName();
+
+ /**
+ * Return both A and AAAA query results regardless the ip address type of the giving network.
+ * Used for probing in NetworkMonitor.
+ */
+ @NonNull
+ public static InetAddress[] getAllByName(@NonNull final DnsResolver dnsResolver,
+ @NonNull final Network network, @NonNull String host, int timeout)
+ throws UnknownHostException {
+ final List<InetAddress> result = new ArrayList<InetAddress>();
+
+ result.addAll(Arrays.asList(
+ getAllByName(dnsResolver, network, host, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
+ timeout)));
+ result.addAll(Arrays.asList(
+ getAllByName(dnsResolver, network, host, TYPE_A, FLAG_NO_CACHE_LOOKUP,
+ timeout)));
+ return result.toArray(new InetAddress[0]);
+ }
+
+ /**
+ * Return dns query result based on the given QueryType(TYPE_A, TYPE_AAAA) or TYPE_ADDRCONFIG.
+ * Used for probing in NetworkMonitor.
+ */
+ @NonNull
+ public static InetAddress[] getAllByName(@NonNull final DnsResolver dnsResolver,
+ @NonNull final Network network, @NonNull final String host, int type, int flag,
+ int timeoutMs) throws UnknownHostException {
+ final CountDownLatch latch = new CountDownLatch(1);
+ final AtomicReference<List<InetAddress>> resultRef = new AtomicReference<>();
+
+ final DnsResolver.Callback<List<InetAddress>> callback =
+ new DnsResolver.Callback<List<InetAddress>>() {
+ @Override
+ public void onAnswer(List<InetAddress> answer, int rcode) {
+ if (rcode == 0) {
+ resultRef.set(answer);
+ }
+ latch.countDown();
+ }
+
+ @Override
+ public void onError(@NonNull DnsResolver.DnsException e) {
+ Log.d(TAG, "DNS error resolving " + host + ": " + e.getMessage());
+ latch.countDown();
+ }
+ };
+ final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+ TrafficStatsConstants.TAG_SYSTEM_PROBE);
+
+ if (type == TYPE_ADDRCONFIG) {
+ dnsResolver.query(network, host, flag, r -> r.run(), null /* cancellationSignal */,
+ callback);
+ } else {
+ dnsResolver.query(network, host, type, flag, r -> r.run(),
+ null /* cancellationSignal */, callback);
+ }
+
+ TrafficStats.setThreadStatsTag(oldTag);
+
+ try {
+ latch.await(timeoutMs, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ }
+
+ final List<InetAddress> result = resultRef.get();
+ if (result == null || result.size() == 0) {
+ throw new UnknownHostException(host);
+ }
+
+ return result.toArray(new InetAddress[0]);
+ }
+}
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index bacec78..8e9350d 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -23,6 +23,7 @@
import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.DnsResolver.FLAG_EMPTY;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
@@ -56,6 +57,8 @@
import static android.net.util.NetworkStackUtils.NAMESPACE_CONNECTIVITY;
import static android.net.util.NetworkStackUtils.isEmpty;
+import static com.android.networkstack.util.DnsUtils.TYPE_ADDRCONFIG;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
@@ -113,6 +116,7 @@
import com.android.networkstack.R;
import com.android.networkstack.metrics.DataStallDetectionStats;
import com.android.networkstack.metrics.DataStallStatsUtils;
+import com.android.networkstack.util.DnsUtils;
import java.io.IOException;
import java.net.HttpURLConnection;
@@ -129,7 +133,6 @@
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
/**
@@ -279,8 +282,8 @@
private final Context mContext;
private final INetworkMonitorCallbacks mCallback;
+ private final Network mCleartextDnsNetwork;
private final Network mNetwork;
- private final Network mNonPrivateDnsBypassNetwork;
private final TelephonyManager mTelephonyManager;
private final WifiManager mWifiManager;
private final ConnectivityManager mCm;
@@ -370,8 +373,8 @@
mCallback = cb;
mDependencies = deps;
mDetectionStatsUtils = detectionStatsUtils;
- mNonPrivateDnsBypassNetwork = network;
- mNetwork = deps.getPrivateDnsBypassNetwork(network);
+ mNetwork = network;
+ mCleartextDnsNetwork = deps.getPrivateDnsBypassNetwork(network);
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -496,7 +499,7 @@
@Override
protected void log(String s) {
- if (DBG) Log.d(TAG + "/" + mNetwork.toString(), s);
+ if (DBG) Log.d(TAG + "/" + mCleartextDnsNetwork.toString(), s);
}
private void validationLog(int probeType, Object url, String msg) {
@@ -517,6 +520,9 @@
return NetworkMonitorUtils.isValidationRequired(mNetworkCapabilities);
}
+ private boolean isPrivateDnsValidationRequired() {
+ return NetworkMonitorUtils.isPrivateDnsValidationRequired(mNetworkCapabilities);
+ }
private void notifyNetworkTested(int result, @Nullable String redirectUrl) {
try {
@@ -604,7 +610,7 @@
return HANDLED;
case CMD_PRIVATE_DNS_SETTINGS_CHANGED: {
final PrivateDnsConfig cfg = (PrivateDnsConfig) message.obj;
- if (!isValidationRequired() || cfg == null || !cfg.inStrictMode()) {
+ if (!isPrivateDnsValidationRequired() || cfg == null || !cfg.inStrictMode()) {
// No DNS resolution required.
//
// We don't force any validation in opportunistic mode
@@ -769,7 +775,7 @@
case CMD_LAUNCH_CAPTIVE_PORTAL_APP:
final Bundle appExtras = new Bundle();
// OneAddressPerFamilyNetwork is not parcelable across processes.
- final Network network = new Network(mNetwork);
+ final Network network = new Network(mCleartextDnsNetwork);
appExtras.putParcelable(ConnectivityManager.EXTRA_NETWORK, network);
final CaptivePortalProbeResult probeRes = mLastPortalProbeResult;
appExtras.putString(EXTRA_CAPTIVE_PORTAL_URL, probeRes.detectUrl);
@@ -840,9 +846,20 @@
// the network so don't bother validating here. Furthermore sending HTTP
// packets over the network may be undesirable, for example an extremely
// expensive metered network, or unwanted leaking of the User Agent string.
+ //
+ // On networks that need to support private DNS in strict mode (e.g., VPNs, but
+ // not networks that don't provide Internet access), we still need to perform
+ // private DNS server resolution.
if (!isValidationRequired()) {
- validationLog("Network would not satisfy default request, not validating");
- transitionTo(mValidatedState);
+ if (isPrivateDnsValidationRequired()) {
+ validationLog("Network would not satisfy default request, "
+ + "resolving private DNS");
+ transitionTo(mEvaluatingPrivateDnsState);
+ } else {
+ validationLog("Network would not satisfy default request, "
+ + "not validating");
+ transitionTo(mValidatedState);
+ }
return HANDLED;
}
mEvaluateAttempts++;
@@ -881,7 +898,7 @@
CustomIntentReceiver(String action, int token, int what) {
mToken = token;
mWhat = what;
- mAction = action + "_" + mNetwork.getNetworkHandle() + "_" + token;
+ mAction = action + "_" + mCleartextDnsNetwork.getNetworkHandle() + "_" + token;
mContext.registerReceiver(this, new IntentFilter(mAction));
}
public PendingIntent getPendingIntent() {
@@ -994,7 +1011,8 @@
private void resolveStrictModeHostname() {
try {
// Do a blocking DNS resolution using the network-assigned nameservers.
- final InetAddress[] ips = mNetwork.getAllByName(mPrivateDnsProviderHostname);
+ final InetAddress[] ips = DnsUtils.getAllByName(mDependencies.getDnsResolver(),
+ mCleartextDnsNetwork, mPrivateDnsProviderHostname, getDnsProbeTimeout());
mPrivateDnsConfig = new PrivateDnsConfig(mPrivateDnsProviderHostname, ips);
validationLog("Strict mode hostname resolved: " + mPrivateDnsConfig);
} catch (UnknownHostException uhe) {
@@ -1033,7 +1051,7 @@
+ oneTimeHostnameSuffix;
final Stopwatch watch = new Stopwatch().start();
try {
- final InetAddress[] ips = mNonPrivateDnsBypassNetwork.getAllByName(host);
+ final InetAddress[] ips = mNetwork.getAllByName(host);
final long time = watch.stop();
final String strIps = Arrays.toString(ips);
final boolean success = (ips != null && ips.length > 0);
@@ -1488,39 +1506,8 @@
@VisibleForTesting
protected InetAddress[] sendDnsProbeWithTimeout(String host, int timeoutMs)
throws UnknownHostException {
- final CountDownLatch latch = new CountDownLatch(1);
- final AtomicReference<List<InetAddress>> resultRef = new AtomicReference<>();
- final DnsResolver.Callback<List<InetAddress>> callback =
- new DnsResolver.Callback<List<InetAddress>>() {
- public void onAnswer(List<InetAddress> answer, int rcode) {
- if (rcode == 0) {
- resultRef.set(answer);
- }
- latch.countDown();
- }
- public void onError(@NonNull DnsResolver.DnsException e) {
- validationLog("DNS error resolving " + host + ": " + e.getMessage());
- latch.countDown();
- }
- };
-
- final int oldTag = TrafficStats.getAndSetThreadStatsTag(
- TrafficStatsConstants.TAG_SYSTEM_PROBE);
- mDependencies.getDnsResolver().query(mNetwork, host, DnsResolver.FLAG_EMPTY,
- r -> r.run() /* executor */, null /* cancellationSignal */, callback);
- TrafficStats.setThreadStatsTag(oldTag);
-
- try {
- latch.await(timeoutMs, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- }
-
- List<InetAddress> result = resultRef.get();
- if (result == null || result.size() == 0) {
- throw new UnknownHostException(host);
- }
-
- return result.toArray(new InetAddress[0]);
+ return DnsUtils.getAllByName(mDependencies.getDnsResolver(), mCleartextDnsNetwork, host,
+ TYPE_ADDRCONFIG, FLAG_EMPTY, timeoutMs);
}
/** Do a DNS resolution of the given server. */
@@ -1565,7 +1552,7 @@
final int oldTag = TrafficStats.getAndSetThreadStatsTag(
TrafficStatsConstants.TAG_SYSTEM_PROBE);
try {
- urlConnection = (HttpURLConnection) mNetwork.openConnection(url);
+ urlConnection = (HttpURLConnection) mCleartextDnsNetwork.openConnection(url);
urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
@@ -1814,7 +1801,7 @@
private void logNetworkEvent(int evtype) {
int[] transports = mNetworkCapabilities.getTransportTypes();
- mMetricsLog.log(mNetwork, transports, new NetworkEvent(evtype));
+ mMetricsLog.log(mCleartextDnsNetwork, transports, new NetworkEvent(evtype));
}
private int networkEventType(ValidationStage s, EvaluationResult r) {
@@ -1836,7 +1823,7 @@
private void maybeLogEvaluationResult(int evtype) {
if (mEvaluationTimer.isRunning()) {
int[] transports = mNetworkCapabilities.getTransportTypes();
- mMetricsLog.log(mNetwork, transports,
+ mMetricsLog.log(mCleartextDnsNetwork, transports,
new NetworkEvent(evtype, mEvaluationTimer.stop()));
mEvaluationTimer.reset();
}
@@ -1850,7 +1837,7 @@
.setReturnCode(probeResult)
.setDurationMs(durationMs)
.build();
- mMetricsLog.log(mNetwork, transports, ev);
+ mMetricsLog.log(mCleartextDnsNetwork, transports, ev);
}
@VisibleForTesting
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index 0dc1cbf..abfb9c8 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -42,10 +42,10 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -66,6 +66,7 @@
import android.net.NetworkInfo;
import android.net.captiveportal.CaptivePortalProbeResult;
import android.net.metrics.IpConnectivityLog;
+import android.net.shared.PrivateDnsConfig;
import android.net.util.SharedLog;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
@@ -73,6 +74,7 @@
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.Looper;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
@@ -131,7 +133,8 @@
private @Mock Random mRandom;
private @Mock NetworkMonitor.Dependencies mDependencies;
private @Mock INetworkMonitorCallbacks mCallbacks;
- private @Spy Network mNetwork = new Network(TEST_NETID);
+ private @Spy Network mCleartextDnsNetwork = new Network(TEST_NETID);
+ private @Mock Network mNetwork;
private @Mock DataStallStatsUtils mDataStallStatsUtils;
private @Mock WifiInfo mWifiInfo;
private @Captor ArgumentCaptor<String> mNetworkTestedRedirectUrlCaptor;
@@ -166,35 +169,108 @@
private static final NetworkCapabilities NO_INTERNET_CAPABILITIES = new NetworkCapabilities()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- private void setDnsAnswers(String[] answers) throws UnknownHostException {
- if (answers == null) {
- doThrow(new UnknownHostException()).when(mNetwork).getAllByName(any());
- doNothing().when(mDnsResolver).query(any(), any(), anyInt(), any(), any(), any());
- return;
+ /**
+ * Fakes DNS responses.
+ *
+ * Allows test methods to configure the IP addresses that will be resolved by
+ * Network#getAllByName and by DnsResolver#query.
+ */
+ class FakeDns {
+ private final ArrayMap<String, List<InetAddress>> mAnswers = new ArrayMap<>();
+ private boolean mNonBypassPrivateDnsWorking = true;
+
+ /** Whether DNS queries on mNonBypassPrivateDnsWorking should succeed. */
+ private void setNonBypassPrivateDnsWorking(boolean working) {
+ mNonBypassPrivateDnsWorking = working;
}
- List<InetAddress> answerList = new ArrayList<>();
- for (String answer : answers) {
- answerList.add(InetAddresses.parseNumericAddress(answer));
+ /** Clears all DNS entries. */
+ private synchronized void clearAll() {
+ mAnswers.clear();
}
- InetAddress[] answerArray = answerList.toArray(new InetAddress[0]);
- doReturn(answerArray).when(mNetwork).getAllByName(any());
+ /** Returns the answer for a given name on the given mock network. */
+ private synchronized List<InetAddress> getAnswer(Object mock, String hostname) {
+ if (mock == mNetwork && !mNonBypassPrivateDnsWorking) {
+ return null;
+ }
+ if (mAnswers.containsKey(hostname)) {
+ return mAnswers.get(hostname);
+ }
+ return mAnswers.get("*");
+ }
- doAnswer((invocation) -> {
- Executor executor = (Executor) invocation.getArgument(3);
- DnsResolver.Callback<List<InetAddress>> callback = invocation.getArgument(5);
- new Handler(Looper.getMainLooper()).post(() -> {
- executor.execute(() -> callback.onAnswer(answerList, 0));
- });
- return null;
- }).when(mDnsResolver).query(eq(mNetwork), any(), anyInt(), any(), any(), any());
+ /** Sets the answer for a given name. */
+ private synchronized void setAnswer(String hostname, String[] answer)
+ throws UnknownHostException {
+ if (answer == null) {
+ mAnswers.remove(hostname);
+ } else {
+ List<InetAddress> answerList = new ArrayList<>();
+ for (String addr : answer) {
+ answerList.add(InetAddresses.parseNumericAddress(addr));
+ }
+ mAnswers.put(hostname, answerList);
+ }
+ }
+
+ /** Simulates a getAllByName call for the specified name on the specified mock network. */
+ private InetAddress[] getAllByName(Object mock, String hostname)
+ throws UnknownHostException {
+ List<InetAddress> answer = getAnswer(mock, hostname);
+ if (answer == null || answer.size() == 0) {
+ throw new UnknownHostException(hostname);
+ }
+ return answer.toArray(new InetAddress[0]);
+ }
+
+ /** Starts mocking DNS queries. */
+ private void startMocking() throws UnknownHostException {
+ // Queries on mNetwork using getAllByName.
+ doAnswer(invocation -> {
+ return getAllByName(invocation.getMock(), invocation.getArgument(0));
+ }).when(mNetwork).getAllByName(any());
+
+ // Queries on mCleartextDnsNetwork using DnsResolver#query.
+ doAnswer(invocation -> {
+ String hostname = (String) invocation.getArgument(1);
+ Executor executor = (Executor) invocation.getArgument(3);
+ DnsResolver.Callback<List<InetAddress>> callback = invocation.getArgument(5);
+
+ List<InetAddress> answer = getAnswer(invocation.getMock(), hostname);
+ if (answer != null && answer.size() > 0) {
+ new Handler(Looper.getMainLooper()).post(() -> {
+ executor.execute(() -> callback.onAnswer(answer, 0));
+ });
+ }
+ // If no answers, do nothing. sendDnsProbeWithTimeout will time out and throw UHE.
+ return null;
+ }).when(mDnsResolver).query(any(), any(), anyInt(), any(), any(), any());
+
+ // Queries on mCleartextDnsNetwork using using DnsResolver#query with QueryType.
+ doAnswer(invocation -> {
+ String hostname = (String) invocation.getArgument(1);
+ Executor executor = (Executor) invocation.getArgument(4);
+ DnsResolver.Callback<List<InetAddress>> callback = invocation.getArgument(6);
+
+ List<InetAddress> answer = getAnswer(invocation.getMock(), hostname);
+ if (answer != null && answer.size() > 0) {
+ new Handler(Looper.getMainLooper()).post(() -> {
+ executor.execute(() -> callback.onAnswer(answer, 0));
+ });
+ }
+ // If no answers, do nothing. sendDnsProbeWithTimeout will time out and throw UHE.
+ return null;
+ }).when(mDnsResolver).query(any(), any(), anyInt(), anyInt(), any(), any(), any());
+ }
}
+ private FakeDns mFakeDns;
+
@Before
public void setUp() throws IOException {
MockitoAnnotations.initMocks(this);
- when(mDependencies.getPrivateDnsBypassNetwork(any())).thenReturn(mNetwork);
+ when(mDependencies.getPrivateDnsBypassNetwork(any())).thenReturn(mCleartextDnsNetwork);
when(mDependencies.getDnsResolver()).thenReturn(mDnsResolver);
when(mDependencies.getRandom()).thenReturn(mRandom);
when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_MODE), anyInt()))
@@ -206,7 +282,7 @@
when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTPS_URL), any()))
.thenReturn(TEST_HTTPS_URL);
- doReturn(mNetwork).when(mNetwork).getPrivateDnsBypassingCopy();
+ doReturn(mCleartextDnsNetwork).when(mNetwork).getPrivateDnsBypassingCopy();
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mCm);
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephony);
@@ -222,6 +298,9 @@
setFallbackSpecs(null); // Test with no fallback spec by default
when(mRandom.nextInt()).thenReturn(0);
+ when(mResources.getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout)))
+ .thenReturn(500);
+
doAnswer((invocation) -> {
URL url = invocation.getArgument(0);
switch(url.toString()) {
@@ -237,11 +316,13 @@
fail("URL not mocked: " + url.toString());
return null;
}
- }).when(mNetwork).openConnection(any());
+ }).when(mCleartextDnsNetwork).openConnection(any());
when(mHttpConnection.getRequestProperties()).thenReturn(new ArrayMap<>());
when(mHttpsConnection.getRequestProperties()).thenReturn(new ArrayMap<>());
- setDnsAnswers(new String[]{"2001:db8::1", "192.0.2.2"});
+ mFakeDns = new FakeDns();
+ mFakeDns.startMocking();
+ mFakeDns.setAnswer("*", new String[]{"2001:db8::1", "192.0.2.2"});
when(mContext.registerReceiver(any(BroadcastReceiver.class), any())).then((invocation) -> {
mRegisteredReceivers.add(invocation.getArgument(0));
@@ -264,6 +345,7 @@
@After
public void tearDown() {
+ mFakeDns.clearAll();
assertTrue(mCreatedNetworkMonitors.size() > 0);
// Make a local copy of mCreatedNetworkMonitors because during the iteration below,
// WrappedNetworkMonitor#onQuitting will delete elements from it on the handler threads.
@@ -284,8 +366,8 @@
private final ConditionVariable mQuitCv = new ConditionVariable(false);
WrappedNetworkMonitor() {
- super(mContext, mCallbacks, mNetwork, mLogger, mValidationLogger, mDependencies,
- mDataStallStatsUtils);
+ super(mContext, mCallbacks, mNetwork, mLogger, mValidationLogger,
+ mDependencies, mDataStallStatsUtils);
}
@Override
@@ -314,23 +396,22 @@
}
}
- private WrappedNetworkMonitor makeMonitor() {
+ private WrappedNetworkMonitor makeMonitor(NetworkCapabilities nc) {
final WrappedNetworkMonitor nm = new WrappedNetworkMonitor();
nm.start();
+ setNetworkCapabilities(nm, nc);
waitForIdle(nm.getHandler());
mCreatedNetworkMonitors.add(nm);
return nm;
}
private WrappedNetworkMonitor makeMeteredNetworkMonitor() {
- final WrappedNetworkMonitor nm = makeMonitor();
- setNetworkCapabilities(nm, METERED_CAPABILITIES);
+ final WrappedNetworkMonitor nm = makeMonitor(METERED_CAPABILITIES);
return nm;
}
private WrappedNetworkMonitor makeNotMeteredNetworkMonitor() {
- final WrappedNetworkMonitor nm = makeMonitor();
- setNetworkCapabilities(nm, NOT_METERED_CAPABILITIES);
+ final WrappedNetworkMonitor nm = makeMonitor(NOT_METERED_CAPABILITIES);
return nm;
}
@@ -595,7 +676,7 @@
@Test
public void testNoInternetCapabilityValidated() throws Exception {
runNetworkTest(NO_INTERNET_CAPABILITIES, NETWORK_TEST_RESULT_VALID);
- verify(mNetwork, never()).openConnection(any());
+ verify(mCleartextDnsNetwork, never()).openConnection(any());
}
@Test
@@ -603,7 +684,7 @@
setSslException(mHttpsConnection);
setPortal302(mHttpConnection);
- final NetworkMonitor nm = makeMonitor();
+ final NetworkMonitor nm = makeMonitor(METERED_CAPABILITIES);
nm.notifyNetworkConnected(TEST_LINK_PROPERTIES, METERED_CAPABILITIES);
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
@@ -638,6 +719,63 @@
}
@Test
+ public void testPrivateDnsSuccess() throws Exception {
+ setStatus(mHttpsConnection, 204);
+ setStatus(mHttpConnection, 204);
+ mFakeDns.setAnswer("dns.google", new String[]{"2001:db8::53"});
+
+ WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();
+ wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
+ wnm.notifyNetworkConnected(TEST_LINK_PROPERTIES, NOT_METERED_CAPABILITIES);
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_VALID), eq(null));
+ }
+
+ @Test
+ public void testPrivateDnsResolutionRetryUpdate() throws Exception {
+ // Set a private DNS hostname that doesn't resolve and expect validation to fail.
+ mFakeDns.setAnswer("dns.google", new String[0]);
+ setStatus(mHttpsConnection, 204);
+ setStatus(mHttpConnection, 204);
+
+ WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();
+ wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
+ wnm.notifyNetworkConnected(TEST_LINK_PROPERTIES, NOT_METERED_CAPABILITIES);
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_INVALID), eq(null));
+
+ // Fix DNS and retry, expect validation to succeed.
+ reset(mCallbacks);
+ mFakeDns.setAnswer("dns.google", new String[]{"2001:db8::1"});
+
+ wnm.forceReevaluation(Process.myUid());
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_VALID), eq(null));
+
+ // Change configuration to an invalid DNS name, expect validation to fail.
+ reset(mCallbacks);
+ mFakeDns.setAnswer("dns.bad", new String[0]);
+ wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.bad", new InetAddress[0]));
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_INVALID), eq(null));
+
+ // Change configuration back to working again, but make private DNS not work.
+ // Expect validation to fail.
+ reset(mCallbacks);
+ mFakeDns.setNonBypassPrivateDnsWorking(false);
+ wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_INVALID), eq(null));
+
+ // Make private DNS work again. Expect validation to succeed.
+ reset(mCallbacks);
+ mFakeDns.setNonBypassPrivateDnsWorking(true);
+ wnm.forceReevaluation(Process.myUid());
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_VALID), eq(null));
+ }
+
+ @Test
public void testDataStall_StallSuspectedAndSendMetrics() throws IOException {
WrappedNetworkMonitor wrappedMonitor = makeNotMeteredNetworkMonitor();
wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
@@ -728,25 +866,27 @@
WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();
final int shortTimeoutMs = 200;
+ // Clear the wildcard DNS response created in setUp.
+ mFakeDns.setAnswer("*", null);
+
String[] expected = new String[]{"2001:db8::"};
- setDnsAnswers(expected);
+ mFakeDns.setAnswer("www.google.com", expected);
InetAddress[] actual = wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
assertIpAddressArrayEquals(expected, actual);
expected = new String[]{"2001:db8::", "192.0.2.1"};
- setDnsAnswers(expected);
- actual = wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
+ mFakeDns.setAnswer("www.googleapis.com", expected);
+ actual = wnm.sendDnsProbeWithTimeout("www.googleapis.com", shortTimeoutMs);
assertIpAddressArrayEquals(expected, actual);
- expected = new String[0];
- setDnsAnswers(expected);
+ mFakeDns.setAnswer("www.google.com", new String[0]);
try {
wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
fail("No DNS results, expected UnknownHostException");
} catch (UnknownHostException e) {
}
- setDnsAnswers(null);
+ mFakeDns.setAnswer("www.google.com", null);
try {
wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
fail("DNS query timed out, expected UnknownHostException");
@@ -841,7 +981,7 @@
}
private NetworkMonitor runNetworkTest(NetworkCapabilities nc, int testResult) {
- final NetworkMonitor monitor = makeMonitor();
+ final NetworkMonitor monitor = makeMonitor(nc);
monitor.notifyNetworkConnected(TEST_LINK_PROPERTIES, nc);
try {
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
diff --git a/packages/PrintSpooler/res/values-mr/strings.xml b/packages/PrintSpooler/res/values-mr/strings.xml
index b055d82..10dec8e 100644
--- a/packages/PrintSpooler/res/values-mr/strings.xml
+++ b/packages/PrintSpooler/res/values-mr/strings.xml
@@ -56,8 +56,8 @@
<string name="print_select_printer" msgid="7388760939873368698">"प्रिंटर निवडा"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"प्रिंटर विसरा"</string>
<plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
- <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर आढळला</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर आढळले</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> प्रिंटर आढळला</item>
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"या प्रिंटर विषयी अधिक माहिती"</string>
@@ -76,8 +76,8 @@
<string name="disabled_services_title" msgid="7313253167968363211">"अक्षम केलल्या सेवा"</string>
<string name="all_services_title" msgid="5578662754874906455">"सर्व सेवा"</string>
<plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
- <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी इंस्टॉल करा</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी इंस्टॉल करा</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> प्रिंटर शोधण्यासाठी इंस्टॉल करा</item>
</plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> प्रिंट करत आहे"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द करत आहे"</string>
diff --git a/packages/PrintSpooler/res/values-pa/strings.xml b/packages/PrintSpooler/res/values-pa/strings.xml
index 4ce8f97..1cacc10 100644
--- a/packages/PrintSpooler/res/values-pa/strings.xml
+++ b/packages/PrintSpooler/res/values-pa/strings.xml
@@ -84,7 +84,7 @@
<string name="failed_notification_title_template" msgid="2256217208186530973">"ਪ੍ਰਿੰਟਰ ਅਸ਼ੁੱਧੀ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"ਪ੍ਰਿੰਟਰ ਬਲੌਕ ਕੀਤਾ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="cancel" msgid="4373674107267141885">"ਰੱਦ ਕਰੋ"</string>
- <string name="restart" msgid="2472034227037808749">"ਰੀਸਟਾਰਟ ਕਰੋ"</string>
+ <string name="restart" msgid="2472034227037808749">"ਮੁੜ-ਸ਼ੁਰੂ ਕਰੋ"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ਪ੍ਰਿੰਟਰ ਲਈ ਕੋਈ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string>
<string name="reason_unknown" msgid="5507940196503246139">"ਅਗਿਆਤ"</string>
<string name="print_service_security_warning_title" msgid="2160752291246775320">"ਕੀ <xliff:g id="SERVICE">%1$s</xliff:g> ਵਰਤਣੀ ਹੈ?"</string>
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 12f5b60..6550ba1 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -107,5 +107,5 @@
<string name="print_error_retry" msgid="1426421728784259538">"Jaribu tena"</string>
<string name="print_error_printer_unavailable" msgid="8985614415253203381">"Printa hii haipatikani kwa sasa."</string>
<string name="print_cannot_load_page" msgid="6179560924492912009">"Haiwezi kupakia onyesho la kuchungulia"</string>
- <string name="print_preparing_preview" msgid="3939930735671364712">"Inaandaa onyesho la kuchungulia..."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Inaandaa onyesho ili ukague kwanza..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-ta/strings.xml b/packages/PrintSpooler/res/values-ta/strings.xml
index dbc1aea..7773718 100644
--- a/packages/PrintSpooler/res/values-ta/strings.xml
+++ b/packages/PrintSpooler/res/values-ta/strings.xml
@@ -33,7 +33,7 @@
<string name="pages_range_example" msgid="8558694453556945172">"எ.கா. 1—5,8,11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"அச்சு மாதிரிக்காட்சி"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"முன்னோட்டத்திற்காக PDF வியூவரை நிறுவுக"</string>
- <string name="printing_app_crashed" msgid="854477616686566398">"அச்சிடல் பயன்பாடு சிதைவடைந்தது"</string>
+ <string name="printing_app_crashed" msgid="854477616686566398">"அச்சிடல் ஆப்ஸ் சிதைவடைந்தது"</string>
<string name="generating_print_job" msgid="3119608742651698916">"அச்சுப் பணியைத் தொடங்குகிறது"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"PDF ஆக சேமி"</string>
<string name="all_printers" msgid="5018829726861876202">"எல்லா அச்சுப்பொறிகளும்…"</string>
diff --git a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
index 4f4aef0..fa2ec55 100644
--- a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
@@ -92,10 +92,7 @@
if (admin.component != null) {
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin.component);
}
- final UserHandle adminUser = admin.user != null
- ? admin.user
- : UserHandle.of(UserHandle.myUserId());
- intent.putExtra(Intent.EXTRA_USER, adminUser);
+ intent.putExtra(Intent.EXTRA_USER, admin.user);
}
return intent;
}
diff --git a/packages/SettingsLib/SearchWidget/res/values-ja/strings.xml b/packages/SettingsLib/SearchWidget/res/values-ja/strings.xml
index 133e525..e9c39b9 100644
--- a/packages/SettingsLib/SearchWidget/res/values-ja/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-ja/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="search_menu" msgid="1604061903696928905">"検索設定"</string>
+ <string name="search_menu" msgid="1604061903696928905">"設定を検索"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-kk/strings.xml b/packages/SettingsLib/SearchWidget/res/values-kk/strings.xml
index 03538a1..fb75455 100644
--- a/packages/SettingsLib/SearchWidget/res/values-kk/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-kk/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="search_menu" msgid="1604061903696928905">"Іздеу параметрлері"</string>
+ <string name="search_menu" msgid="1604061903696928905">"Параметрлерді іздеу"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-ml/strings.xml b/packages/SettingsLib/SearchWidget/res/values-ml/strings.xml
index ada622f..ecbfe2e 100644
--- a/packages/SettingsLib/SearchWidget/res/values-ml/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-ml/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="search_menu" msgid="1604061903696928905">"തിരയൽ ക്രമീകരണം"</string>
+ <string name="search_menu" msgid="1604061903696928905">"ക്രമീകരണത്തിൽ തിരയുക"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 80904b9..0116d0d 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan nie skandeer vir netwerke nie"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Geen"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Gestoor"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Ontkoppel"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Gedeaktiveer"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-opstelling het misluk"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nie gekoppel nie weens laegehalte-netwerk"</string>
@@ -322,7 +323,7 @@
<string name="debug_applications_category" msgid="4206913653849771549">"Programme"</string>
<string name="immediately_destroy_activities" msgid="1579659389568133959">"Moenie aktiwiteite behou nie"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Vernietig elke aktiwiteit sodra die gebruiker dit verlaat"</string>
- <string name="app_process_limit_title" msgid="4280600650253107163">"Agtergrondproses-limiet"</string>
+ <string name="app_process_limit_title" msgid="4280600650253107163">"Agtergrondproseslimiet"</string>
<string name="show_all_anrs" msgid="4924885492787069007">"Wys agtergrond-ANR\'e"</string>
<string name="show_all_anrs_summary" msgid="6636514318275139826">"Wys Program Reageer Nie-dialoog vir agtergrondprogramme"</string>
<string name="show_notification_channel_warnings" msgid="1399948193466922683">"Wys kennisgewingkanaalwaarskuwings"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index f249eaf..b914b07 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ለአውታረመረቦች መቃኘት አይቻልም"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"የለም"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ተቀምጧል"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"ተቋርጧል"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ተሰናክሏል"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"የአይ.ፒ. ውቅረት መሰናከል"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"በዝቅተኛ አውታረ መረብ ምክንያት አልተገናኘም"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 5eccd1b..0a9edb5 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"لا يمكن فحص الشبكات"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"بلا أمان"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"تم الحفظ"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"غير متصلة"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"غير مفعّلة"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"تعذّرت تهيئة عنوان IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"الجهاز غير متصل بسبب انخفاض جودة الشبكة"</string>
@@ -207,9 +208,9 @@
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"عرض زر في قائمة خيارات التشغيل لإعداد تقرير بالأخطاء"</string>
<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">"تفعيل سجلّ تطفّل بواجهة وحدة تحكّم المضيف عبر بلوتوث"</string>
+ <string name="bt_hci_snoop_log" msgid="3340699311158865670">"تفعيل سجلّ تطفل بواجهة وحدة تحكم المضيف في بلوتوث"</string>
<string name="bt_hci_snoop_log_summary" msgid="8857606786588106495">"رَقمِن محتوى حزم بيانات البلوتوث. (تبديل البلوتوث بعد تغيير هذا الإعداد)"</string>
- <string name="oem_unlock_enable" msgid="6040763321967327691">"إلغاء قفل المصنّع الأصلي للجهاز"</string>
+ <string name="oem_unlock_enable" msgid="6040763321967327691">"فتح قفل المصنّع الأصلي للجهاز"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"السماح بإلغاء قفل برنامج bootloader"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"هل تريد السماح بإلغاء قفل المصنّع الأصلي للجهاز؟"</string>
<string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"تحذير: لن تعمل ميزات الحماية على هذا الجهاز أثناء تشغيل هذا الإعداد."</string>
@@ -282,7 +283,7 @@
<string name="wait_for_debugger" msgid="1202370874528893091">"انتظار برنامج التصحيح"</string>
<string name="wait_for_debugger_summary" msgid="1766918303462746804">"ينتظر التطبيق قيد التصحيح انضمام برنامج التصحيح قبل التنفيذ"</string>
<string name="debug_input_category" msgid="1811069939601180246">"الإدخال"</string>
- <string name="debug_drawing_category" msgid="6755716469267367852">"رسم"</string>
+ <string name="debug_drawing_category" msgid="6755716469267367852">"الرسم"</string>
<string name="debug_hw_drawing_category" msgid="6220174216912308658">"عرض تسارع الأجهزة"</string>
<string name="media_category" msgid="4388305075496848353">"الوسائط"</string>
<string name="debug_monitoring_category" msgid="7640508148375798343">"المراقبة"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index b8bc2af..fddfb05 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"নেটৱৰ্ক বিচাৰি স্কেন কৰিব পৰা নাই"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"নাই"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ছেভ কৰি থোৱা নেটৱৰ্কসমূহ"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"সংযোগ বিচ্ছিন্ন"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"নিষ্ক্ৰিয় হৈ আছে"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP কনফিগাৰেশ্বন বিফল হৈছে"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"নিম্নমানৰ নেটৱৰ্কৰ বাবে সংযোগ কৰা হোৱা নাই"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index e719ff2..642b81c 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Şəbəkə axtarmaq olmur"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Heç biri"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Yadda saxlanılan"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Bağlantı kəsildi"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiv"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Konfiqurasiya Uğursuzluğu"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Şəbəkə keyfiyyəti aşağı olduğuna görə qoşulmadı"</string>
@@ -288,7 +289,7 @@
<string name="debug_monitoring_category" msgid="7640508148375798343">"Monitorinq"</string>
<string name="strict_mode" msgid="1938795874357830695">"Məhdud rejim aktivdir"</string>
<string name="strict_mode_summary" msgid="142834318897332338">"Əsas axında tətbiqlərin əlavə əməliyyatlar etməsi zamanı ekran işartısı olsun"</string>
- <string name="pointer_location" msgid="6084434787496938001">"Pointer yeri"</string>
+ <string name="pointer_location" msgid="6084434787496938001">"Kursor yeri"</string>
<string name="pointer_location_summary" msgid="840819275172753713">"Cari əlaqə datasını göstərən ekran örtüyü"</string>
<string name="show_touches" msgid="2642976305235070316">"Tıklamaları göstərin"</string>
<string name="show_touches_summary" msgid="6101183132903926324">"Tıklamalar üçün vizual cavab rəylərini göstərin"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index c524504..4fea77a 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nije moguće skenirati mreže"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Veza je prekinuta"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfiguracija je otkazala"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nije povezano zbog lošeg kvaliteta mreže"</string>
@@ -152,7 +153,7 @@
<string name="launch_defaults_some" msgid="313159469856372621">"Podešene su neke podrazumevane vrednosti"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nisu podešene podrazumevane vrednosti"</string>
<string name="tts_settings" msgid="8186971894801348327">"Podešavanja prelaska iz teksta u govor"</string>
- <string name="tts_settings_title" msgid="1237820681016639683">"Izlaz za pretvaranje teksta u govor"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Pretvaranje teksta u govor"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina izgovaranja teksta"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"Nivo"</string>
@@ -207,7 +208,7 @@
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Prikaži dugme u meniju napajanja za pravljenje izveštaja o greškama"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Ne zaključavaj"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"Ekran neće biti u režimu spavanja tokom punjenja"</string>
- <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Omogući snoop evidenciju za Bluetooth HCI"</string>
+ <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Omogući snoop evid. za Bluetooth HCI"</string>
<string name="bt_hci_snoop_log_summary" msgid="8857606786588106495">"Snimi Bluetooth pakete. (Uključite/isključite Bluetooth kada promenite ovo podešavanje)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"Otključavanje OEM-a"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Dozvoli otključavanje funkcije za pokretanje"</string>
@@ -311,8 +312,8 @@
<string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Nametni smer rasporeda ekrana zdesna nalevo za sve lokalitete"</string>
<string name="force_msaa" msgid="7920323238677284387">"Nametni 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Omogući 4x MSAA u OpenGL ES 2.0 aplikacijama"</string>
- <string name="show_non_rect_clip" msgid="505954950474595172">"Otkloni greške isecanja oblasti koje nisu pravougaonog oblika"</string>
- <string name="track_frame_time" msgid="6094365083096851167">"Penderuj pomoću HWUI-a"</string>
+ <string name="show_non_rect_clip" msgid="505954950474595172">"Otkloni greške isecanja oblasti nepravougaonog oblika"</string>
+ <string name="track_frame_time" msgid="6094365083096851167">"Renderuj pomoću HWUI-a"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Omogući slojeve za otklanjanje grešaka GPU-a"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Omogući učitavanje otk. greš. GPU-a u apl. za otk. greš."</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Razmera animacije prozora"</string>
@@ -363,7 +364,7 @@
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertuj..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Već se koristi šifrovanje datoteka"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"Konvertovanje u šifrovanje pojedinačnih datoteka"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Konvertujte šifrovanje particije podataka u šifrovanje pojedinačnih datoteka.\n !!Upozorenje!! Time brišete sve podatke.\n Ovo je alfa verzija funkcije i verovatno neće funkcionisati ispravno.\n Pritisnite „Izbriši i konvertuj...“ da biste nastavili."</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Konvertujte šifrovanje particije podataka u šifrovanje pojedinačnih datoteka.\n !!Upozorenje!! Time brišete sve podatke.\n Ovo je alfa verzija funkcije i verovatno neće raditi ispravno.\n Pritisnite „Izbriši i konvertuj...“ da biste nastavili."</string>
<string name="button_convert_fbe" msgid="5152671181309826405">"Izbriši i konvertuj..."</string>
<string name="picture_color_mode" msgid="4560755008730283695">"Režim boja slika"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"Koristi sRGB"</string>
@@ -459,7 +460,7 @@
<string name="alarm_template" msgid="4996153414057676512">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Trajanje"</string>
- <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Uvek pitaj"</string>
+ <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Pitaj svaki put"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Upravo"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Ovaj uređaj"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 162e95f..5013300 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не атрымлiваецца выканаць сканаванне для сетак"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Няма"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Захавана"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Адключана"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Адключана"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Збой канфігурацыі IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Няма падключэння з-за нізкай якасці сеткі"</string>
@@ -274,7 +275,7 @@
<string name="hdcp_checking_title" msgid="8605478913544273282">"Праверка HDCP"</string>
<string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Усталяваць рэжым праверкі HDCP"</string>
<string name="debug_debugging_category" msgid="6781250159513471316">"Адладка"</string>
- <string name="debug_app" msgid="8349591734751384446">"Выберыце праграму для адладкі"</string>
+ <string name="debug_app" msgid="8349591734751384446">"Выбраць праграму для адладкі"</string>
<string name="debug_app_not_set" msgid="718752499586403499">"Праграма для адладкi не зададзена"</string>
<string name="debug_app_set" msgid="2063077997870280017">"Адладка прыкладання: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"Выберыце прыкладанне"</string>
@@ -303,7 +304,7 @@
<string name="disable_overlays_summary" msgid="3578941133710758592">"Заўсёды выкарыстоўваць GPU для экраннай кампаноўкі"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Сімуляцыя каляр. прасторы"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"Уключэнне слядоў OpenGL"</string>
- <string name="usb_audio_disable_routing" msgid="8114498436003102671">"Адключыць аўдыёмаршрутызацыю USB"</string>
+ <string name="usb_audio_disable_routing" msgid="8114498436003102671">"Адключыць аўдыямаршрутызацыю USB"</string>
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Выкл. аўтаперанакіраванне на USB-аўдыяпрылады"</string>
<string name="debug_layout" msgid="5981361776594526155">"Паказаць межы макета"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"Паказаць межы кліпа, палі і г. д."</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index a12ae9f..18bbc80 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не може да се сканира за мрежи"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Няма"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Запазено"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Няма връзка"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Деактивирани"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Неуспешно конфигуриране на IP адреса"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Не е установена връзка поради ниското качество на мрежата"</string>
@@ -313,7 +314,7 @@
<string name="force_msaa_summary" msgid="9123553203895817537">"Активиране на 4x MSAA в прилож. с OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"Отстр. на грешки при неправоъг. изрязване"</string>
<string name="track_frame_time" msgid="6094365083096851167">"Изобр. на HWUI: Профилир."</string>
- <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Слоеве за отстр. на грешки в ГП: Актив."</string>
+ <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Активиране на слоевете за отстр. на грешки в ГП"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Разреш. на зарежд. на слоевете за отстр. на грешки в ГП за съотв. прилож."</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Скала на аним.: Прозорец"</string>
<string name="transition_animation_scale_title" msgid="387527540523595875">"Скала на преходната анимация"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index a23c649..9f9bf04 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"নেটওয়ার্কগুলির জন্য স্ক্যান করা যাবে না"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"কোনো কিছুই নয়"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"সংরক্ষিত"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"কানেকশন নেই"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"অক্ষম হয়েছে"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP কনফিগারেশনের ব্যর্থতা"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"খারাপ নেটওয়ার্কের কারণে কানেক্ট নয়"</string>
@@ -286,7 +287,7 @@
<string name="debug_hw_drawing_category" msgid="6220174216912308658">"হার্ডওয়্যার দ্বারা চালিত রেন্ডারিং"</string>
<string name="media_category" msgid="4388305075496848353">"মিডিয়া"</string>
<string name="debug_monitoring_category" msgid="7640508148375798343">"পর্যবেক্ষণে রাখা"</string>
- <string name="strict_mode" msgid="1938795874357830695">"কঠোর মোড সক্ষম"</string>
+ <string name="strict_mode" msgid="1938795874357830695">"স্ট্রিক্ট মোড চালু আছে"</string>
<string name="strict_mode_summary" msgid="142834318897332338">"মুখ্য থ্রেডে অ্যাপ্লিকেশানগুলির দীর্ঘ অ্যাক্টিভিটির সময় স্ক্রিন ফ্ল্যাশ করে"</string>
<string name="pointer_location" msgid="6084434787496938001">"পয়েন্টারের লোকেশন"</string>
<string name="pointer_location_summary" msgid="840819275172753713">"স্ক্রিন ওভারলে বর্তমান স্পর্শ ডেটা দেখাচ্ছে"</string>
@@ -299,11 +300,11 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"হার্ডওয়্যার স্তর আপডেটগুলি প্রদর্শন করুন"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"যখন হার্ডওয়্যার স্তরগুলি আপডেট হয় তখন সেগুলিকে সবুজ রঙে ফ্ল্যাশ করুন"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"ডিবাগ GPU ওভারড্র"</string>
- <string name="disable_overlays" msgid="2074488440505934665">"HW আচ্ছাদনগুলি অক্ষম করুন"</string>
+ <string name="disable_overlays" msgid="2074488440505934665">"HW ওভারলে বন্ধ করুন"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"সর্বদা স্ক্রিন কম্পোসিটিংয়ের জন্য GPU ব্যবহার করুন"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"রঙ স্থান নকল করুন"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"OpenGL ট্রেসগুলি সক্ষম করুন"</string>
- <string name="usb_audio_disable_routing" msgid="8114498436003102671">"USB অডিও রাউটিং অক্ষম করুন"</string>
+ <string name="usb_audio_disable_routing" msgid="8114498436003102671">"USB অডিও রাউটিং বন্ধ করুন"</string>
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"USB অডিও যন্ত্রানুষঙ্গে অটোমেটিক রাউটিং অক্ষম করুন"</string>
<string name="debug_layout" msgid="5981361776594526155">"লেআউট সীমাগুলি দেখান"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"ক্লিপ বাউন্ড, মার্জিন ইত্যাদি দেখান"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index ddd69d1..bbc89d4 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ne može skenirati mreže"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Veza je prekinuta"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Greška u konfiguraciji IP-a"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Niste povezani zbog slabog kvaliteta mreže"</string>
@@ -55,7 +56,7 @@
<string name="osu_sign_up_complete" msgid="8207626049093289203">"Registracija je završena. Povezivanje…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"Veoma sporo"</string>
<string name="speed_label_slow" msgid="813109590815810235">"Sporo"</string>
- <string name="speed_label_okay" msgid="2331665440671174858">"UREDU"</string>
+ <string name="speed_label_okay" msgid="2331665440671174858">"Uredu"</string>
<string name="speed_label_medium" msgid="3175763313268941953">"Srednja brzina"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Brzo"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Veoma brzo"</string>
@@ -155,7 +156,7 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Pretvaranje teksta u govor"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina kojom se izgovara tekst"</string>
- <string name="tts_default_pitch_title" msgid="6135942113172488671">"Visina"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Visina glasa"</string>
<string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utiče na ton sintetiziranog govora"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Korištenje sistemskog jezika"</string>
@@ -213,7 +214,7 @@
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Dozvoli otključavanje bootloadera"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"Želite li dozvoliti OEM otključavanje?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"UPOZORENJE: Funkcije zaštite ovog uređaja neće funkcionirati dok je ova postavka uključena."</string>
- <string name="mock_location_app" msgid="7966220972812881854">"Odaberite aplikaciju za lažnu lokaciju"</string>
+ <string name="mock_location_app" msgid="7966220972812881854">"Odabir aplikacije za lažnu lokaciju"</string>
<string name="mock_location_app_not_set" msgid="809543285495344223">"Aplikacija za lažnu lokaciju nije postavljena"</string>
<string name="mock_location_app_set" msgid="8966420655295102685">"Aplikacija za lažnu lokaciju: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 888a58b..8a4ab91 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"No es poden cercar xarxes"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Cap"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Desat"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Desconnectada"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desactivat"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuració d\'IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"No s\'ha connectat a la xarxa perquè la qualitat és baixa"</string>
@@ -205,7 +206,7 @@
<string name="clear_adb_keys" msgid="4038889221503122743">"Revoca autoritzacions de depuració per USB"</string>
<string name="bugreport_in_power" msgid="7923901846375587241">"Drecera per a informe d\'errors"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Mostra un botó al menú d\'engegada per crear un informe d\'errors"</string>
- <string name="keep_screen_on" msgid="1146389631208760344">"Pantalla sempre activa"</string>
+ <string name="keep_screen_on" msgid="1146389631208760344">"Pantalla activa"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"La pantalla no entra mai en mode de repòs si el dispositiu s\'està carregant"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"Activa registre de Bluetooth HCI"</string>
<string name="bt_hci_snoop_log_summary" msgid="8857606786588106495">"Captura els paquets de Bluetooth. Activa el Bluetooth un cop hagis canviat aquesta opció."</string>
@@ -251,7 +252,7 @@
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Selecciona la mida de la memòria intermèdia del registre"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vols esborrar l\'emmagatzematge persistent del registrador?"</string>
<string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Quan deixem de supervisar amb el registrador persistent, hem d\'esborrar les dades del registrador que hi ha al teu dispositiu."</string>
- <string name="select_logpersist_title" msgid="7530031344550073166">"Desa dades del registrador de manera permanent al dispositiu"</string>
+ <string name="select_logpersist_title" msgid="7530031344550073166">"Desa dades registrador permanentment"</string>
<string name="select_logpersist_dialog_title" msgid="4003400579973269060">"Selecciona memòries interm. de registre per emmag. de manera persistent al disp."</string>
<string name="select_usb_configuration_title" msgid="2649938511506971843">"Selecciona configuració d\'USB"</string>
<string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"Selecciona configuració d\'USB"</string>
@@ -280,7 +281,7 @@
<string name="select_application" msgid="5156029161289091703">"Selecciona una aplicació"</string>
<string name="no_application" msgid="2813387563129153880">"Cap"</string>
<string name="wait_for_debugger" msgid="1202370874528893091">"Espera el depurador"</string>
- <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Abans d\'executar-se, l\'aplicació de depuració espera que es connecti el depurador"</string>
+ <string name="wait_for_debugger_summary" msgid="1766918303462746804">"L\'aplicació depurada espera que es connecti el depurador abans d\'executar-se"</string>
<string name="debug_input_category" msgid="1811069939601180246">"Introducció de text"</string>
<string name="debug_drawing_category" msgid="6755716469267367852">"Dibuix"</string>
<string name="debug_hw_drawing_category" msgid="6220174216912308658">"Renderització accelerada per maquinari"</string>
@@ -294,17 +295,17 @@
<string name="show_touches_summary" msgid="6101183132903926324">"Mostra la ubicació visual dels tocs"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"Canvis de superfície"</string>
<string name="show_screen_updates_summary" msgid="2569622766672785529">"Il·lumina superfícies de finestres en actualitzar-se"</string>
- <string name="show_hw_screen_updates" msgid="4117270979975470789">"Mostra actualitzacions"</string>
+ <string name="show_hw_screen_updates" msgid="4117270979975470789">"Actualitzacions de visualitzacions"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Il·lumina visualitzacions de finestres creades"</string>
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Mostra actualitzacions de capes de maquinari"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Il·lumina capes de maquinari en verd en actualitzar-se"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depura sobredibuix de GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Desactiva superposicions maquinari"</string>
- <string name="disable_overlays_summary" msgid="3578941133710758592">"Utilitza sempre GPU per combinar pantalles"</string>
+ <string name="disable_overlays_summary" msgid="3578941133710758592">"Utilitza sempre GPU per a la composició de pantalles"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simula l\'espai de color"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"Activa traces d\'OpenGL"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"Desactiva l\'encaminament d\'àudio per USB"</string>
- <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Desactiva l\'encaminament automàtic als perifèrics d\'àudio USB"</string>
+ <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Desactiva l\'encaminament automàtic a perifèrics d\'àudio USB"</string>
<string name="debug_layout" msgid="5981361776594526155">"Mostra límits de disposició"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"Mostra els límits de clips, els marges, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Força direcció dreta-esquerra"</string>
@@ -326,13 +327,13 @@
<string name="show_all_anrs" msgid="4924885492787069007">"Mostra ANR en segon pla"</string>
<string name="show_all_anrs_summary" msgid="6636514318275139826">"Mostra el quadre de diàleg L\'aplicació no respon per a aplicacions en segon pla"</string>
<string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostra avisos del canal de notificacions"</string>
- <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Mostra un avís a la pantalla quan una aplicació publica una notificació sense un canal vàlid"</string>
+ <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Mostra un avís en pantalla quan una aplicació publica una notificació sense un canal vàlid"</string>
<string name="force_allow_on_external" msgid="3215759785081916381">"Força permetre aplicacions de manera externa"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"Permet que qualsevol aplicació es pugui escriure en un dispositiu d’emmagatzematge extern, independentment dels valors definits"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Força l\'ajust de la mida de les activitats"</string>
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors definits."</string>
- <string name="enable_freeform_support" msgid="1461893351278940416">"Activa les finestres de format lliure"</string>
- <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa la compatibilitat amb finestres de format lliure experimentals."</string>
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Activa les finestres de forma lliure"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa la compatibilitat amb finestres de forma lliure experimentals."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Contrasenya per a còpies d\'ordinador"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Les còpies de seguretat completes d\'ordinador no estan protegides"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toca per canviar o suprimir la contrasenya per a les còpies de seguretat completes de l\'ordinador"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 05889a4..0163382 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nelze hledat sítě"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Žádné"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Uloženo"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Odpojeno"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Vypnuto"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Selhání konfigurace protokolu IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nejste připojeni, protože síť je příliš slabá"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 6afb477..04ef33d 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Der kan ikke søges efter netværk"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Gemt"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Afbrudt"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiveret"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurationsfejl"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ingen forbindelse på grund af lav netværkskvalitet"</string>
@@ -273,10 +274,10 @@
<string name="enable_terminal_summary" msgid="67667852659359206">"Aktivér terminalappen, der giver lokal shell-adgang"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-kontrol"</string>
<string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Angiv HDCP-kontroladfærd"</string>
- <string name="debug_debugging_category" msgid="6781250159513471316">"Fejlfinding"</string>
+ <string name="debug_debugging_category" msgid="6781250159513471316">"Fejlretning"</string>
<string name="debug_app" msgid="8349591734751384446">"Vælg app til fejlretning"</string>
- <string name="debug_app_not_set" msgid="718752499586403499">"Ingen applikation til fejlretning er angivet"</string>
- <string name="debug_app_set" msgid="2063077997870280017">"Applikation til fejlfinding: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="debug_app_not_set" msgid="718752499586403499">"Ingen app til fejlretning er angivet"</string>
+ <string name="debug_app_set" msgid="2063077997870280017">"App til fejlretning: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"Vælg applikation"</string>
<string name="no_application" msgid="2813387563129153880">"Ingen"</string>
<string name="wait_for_debugger" msgid="1202370874528893091">"Vent på fejlfinder"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index ca74820..e705d82 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Netzwerkscan nicht möglich"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Keine"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Gespeichert"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Nicht verbunden"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiviert"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-Konfigurationsfehler"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Keine Verbindung aufgrund der geringen Netzwerkqualität"</string>
@@ -244,9 +245,9 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostname des DNS-Anbieters eingeben"</string>
<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_verbose_logging_summary" msgid="6615071616111731958">"WLAN-Protokollierungsebene erhöhen, in WiFi Picker pro SSID RSSI anzeigen"</string>
<string name="wifi_metered_label" msgid="4514924227256839725">"Kostenpflichtig"</string>
- <string name="wifi_unmetered_label" msgid="6124098729457992931">"Nicht kostenpflichtig"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Kostenlos"</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>
@@ -258,7 +259,7 @@
<string name="allow_mock_location" msgid="2787962564578664888">"Simulierte Standorte"</string>
<string name="allow_mock_location_summary" msgid="317615105156345626">"Simulierte Standorte zulassen"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"Inspektion der Anzeigeattribute aktivieren"</string>
- <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Die mobile Datennutzung bleibt auch dann aktiviert, wenn WLAN aktiviert ist. Dies dient einem schnelleren Wechsel zwischen Netzwerken."</string>
+ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Die mobile Datennutzung bleibt auch dann aktiviert, wenn WLAN aktiviert ist. Das ermöglicht einen schnelleren Wechsel zwischen Netzwerken."</string>
<string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Falls verfügbar, Hardwarebeschleunigung für Tethering verwenden"</string>
<string name="adb_warning_title" msgid="6234463310896563253">"USB-Debugging zulassen?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"USB-Debugging ist nur für Entwicklungszwecke vorgesehen. Damit kannst du Daten zwischen deinem Computer und deinem Gerät kopieren, Apps auf deinem Gerät ohne Benachrichtigung installieren und Protokolldaten lesen."</string>
@@ -289,15 +290,15 @@
<string name="strict_mode" msgid="1938795874357830695">"Strikter Modus aktiviert"</string>
<string name="strict_mode_summary" msgid="142834318897332338">"Bei langen App-Operationen im Hauptthread blinkt Bildschirm"</string>
<string name="pointer_location" msgid="6084434787496938001">"Zeigerposition"</string>
- <string name="pointer_location_summary" msgid="840819275172753713">"Overlay mit aktuellen Daten zu Tippaktionen"</string>
+ <string name="pointer_location_summary" msgid="840819275172753713">"Overlay mit aktuellen Daten zu Tippaktionen anzeigen"</string>
<string name="show_touches" msgid="2642976305235070316">"Fingertipps anzeigen"</string>
- <string name="show_touches_summary" msgid="6101183132903926324">"Visuelles Feedback für Fingertipps anzeigen"</string>
+ <string name="show_touches_summary" msgid="6101183132903926324">"Bei Fingertipps visuelles Feedback anzeigen"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"Oberflächenaktualisierungen anzeigen"</string>
<string name="show_screen_updates_summary" msgid="2569622766672785529">"Gesamte Fensteroberflächen blinken bei Aktualisierung"</string>
<string name="show_hw_screen_updates" msgid="4117270979975470789">"Updates anzeigen"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Ansichten in Fenstern blinken beim Rendern"</string>
- <string name="show_hw_layers_updates" msgid="5645728765605699821">"Hardwareebenen-Updates anzeigen"</string>
- <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Hardwareebenen blinken beim Aktualisieren grün"</string>
+ <string name="show_hw_layers_updates" msgid="5645728765605699821">"Aktualisierungen von Hardwareschichten anzeigen"</string>
+ <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Hardwareschichten blinken beim Aktualisieren grün"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU-Overdraw debuggen"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW-Overlays deaktivieren"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Für Bildschirm-Compositing immer GPU verwenden"</string>
@@ -315,9 +316,9 @@
<string name="track_frame_time" msgid="6094365083096851167">"HWUI-Rendering für Profil"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"GPU-Debug-Ebenen zulassen"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Debug-Apps das Laden von GPU-Debug-Ebenen erlauben"</string>
- <string name="window_animation_scale_title" msgid="6162587588166114700">"Maßstab Fensteranimation"</string>
- <string name="transition_animation_scale_title" msgid="387527540523595875">"Maßstab Übergangsanimation"</string>
- <string name="animator_duration_scale_title" msgid="3406722410819934083">"Maßstab für Animatorzeit"</string>
+ <string name="window_animation_scale_title" msgid="6162587588166114700">"Fensteranimationsfaktor"</string>
+ <string name="transition_animation_scale_title" msgid="387527540523595875">"Übergangsanimationsfaktor"</string>
+ <string name="animator_duration_scale_title" msgid="3406722410819934083">"Animationsdauerfaktor"</string>
<string name="overlay_display_devices_title" msgid="5364176287998398539">"Sekundäre Displays simulieren"</string>
<string name="debug_applications_category" msgid="4206913653849771549">"Apps"</string>
<string name="immediately_destroy_activities" msgid="1579659389568133959">"Aktivitäten nicht speichern"</string>
@@ -411,7 +412,7 @@
<string name="disabled" msgid="9206776641295849915">"Deaktiviert"</string>
<string name="external_source_trusted" msgid="2707996266575928037">"Zugelassen"</string>
<string name="external_source_untrusted" msgid="2677442511837596726">"Nicht zulässig"</string>
- <string name="install_other_apps" msgid="6986686991775883017">"Unbekannte Apps installieren"</string>
+ <string name="install_other_apps" msgid="6986686991775883017">"Installieren unbekannter Apps"</string>
<string name="home" msgid="3256884684164448244">"Startseite \"Einstellungen\""</string>
<string-array name="battery_labels">
<item msgid="8494684293649631252">"0 %"</item>
@@ -431,7 +432,7 @@
<string name="retail_demo_reset_next" msgid="8356731459226304963">"Weiter"</string>
<string name="retail_demo_reset_title" msgid="696589204029930100">"Passwort erforderlich"</string>
<string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktive Eingabemethoden"</string>
- <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Systemsprache verwenden"</string>
+ <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Systemsprachen verwenden"</string>
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Einstellungen für <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> konnten nicht geöffnet werden."</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Diese Eingabemethode kann den gesamten von dir eingegebenen Text erfassen, einschließlich personenbezogener Daten wie Passwörter und Kreditkartennummern. Sie ist Teil der App \"<xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>\". Möchtest du diese Eingabemethode verwenden?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Hinweis: Nach einem Neustart wird diese App erst gestartet, wenn du dein Smartphone entsperrst"</string>
@@ -460,6 +461,6 @@
<string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Dauer"</string>
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Jedes Mal fragen"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Bis zur Deaktivierung"</string>
- <string name="time_unit_just_now" msgid="6363336622778342422">"Gerade eben"</string>
+ <string name="time_unit_just_now" msgid="6363336622778342422">"gerade eben"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Dieses Gerät"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index a628c07..031cd0d 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Δεν είναι δυνατή η σάρωση για δίκτυα"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Καμία"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Αποθηκευμένο"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Αποσυνδεδεμένο"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Απενεργοποιημένο"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Αποτυχία διαμόρφωσης διεύθυνσης IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Δεν υπάρχει σύνδεση λόγω χαμηλής ποιότητας δικτύου"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 8758ea1..5728800 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Disconnected"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Not connected due to low quality network"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 8758ea1..5728800 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Disconnected"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Not connected due to low quality network"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 8758ea1..5728800 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Disconnected"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Not connected due to low quality network"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 8758ea1..5728800 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Disconnected"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Not connected due to low quality network"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index a9f6190..460442b 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Disconnected"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Not connected due to low quality network"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index d52f52c..22d39c5 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"No se pueden buscar las redes."</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Ninguna"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Guardada"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Desconectada"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Inhabilitada"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuración IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"No se estableció conexión debido a la mala calidad de la red"</string>
@@ -258,7 +259,7 @@
<string name="allow_mock_location" msgid="2787962564578664888">"Ubicaciones de prueba"</string>
<string name="allow_mock_location_summary" msgid="317615105156345626">"Permitir ubicaciones de prueba"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"Habilitar inspección de atributos de vista"</string>
- <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Siempre mantén los datos móviles activos, incluso cuando esté activada la conexión Wi‑Fi (para cambiar de red de forma rápida)."</string>
+ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Mantener siempre los datos móviles activos, incluso cuando esté activada la conexión Wi‑Fi (para cambiar de red de forma rápida)."</string>
<string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Usar la aceleración de hardware de conexión mediante dispositivo portátil si está disponible"</string>
<string name="adb_warning_title" msgid="6234463310896563253">"¿Permitir depuración por USB?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"La depuración por USB solo está indicada para actividades de programación. Úsala para copiar datos entre tu computadora y el dispositivo, para instalar aplicaciones en el dispositivo sin recibir notificaciones y para leer datos de registro."</string>
@@ -294,7 +295,7 @@
<string name="show_touches_summary" msgid="6101183132903926324">"Mostrar información visual para presiones"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"Ver actualiz. de superficie"</string>
<string name="show_screen_updates_summary" msgid="2569622766672785529">"Destello en superficie por actualización"</string>
- <string name="show_hw_screen_updates" msgid="4117270979975470789">"Mostrar actualizaciones"</string>
+ <string name="show_hw_screen_updates" msgid="4117270979975470789">"Mostrar cambios de vista"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Mostrar vistas de ventanas procesadas"</string>
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Ver actualiz. de capas de hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Luz verde en capas de hardware al actualizarse"</string>
@@ -326,7 +327,7 @@
<string name="show_all_anrs" msgid="4924885492787069007">"Mostrar ANR en 2.° plano"</string>
<string name="show_all_anrs_summary" msgid="6636514318275139826">"Mostrar diálogo cuando las apps en segundo plano no responden"</string>
<string name="show_notification_channel_warnings" msgid="1399948193466922683">"Alertas de notificaciones"</string>
- <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"App que publica notificación sin canal válido"</string>
+ <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Advertencia en pantalla cuando una app publica una notificación sin canal válido"</string>
<string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permisos en almacenamiento externo"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"Cualquier app puede escribirse en un almacenamiento externo, sin importar los valores del manifiesto"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forzar actividades para que cambien de tamaño"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index b68322d..533296c 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"No se puede buscar redes."</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Ninguna"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Guardado"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Desconectada"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Inhabilitado"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuración de IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"No conectado debido a la baja calidad de la red"</string>
@@ -218,20 +219,20 @@
<string name="mock_location_app_set" msgid="8966420655295102685">"Aplicación para simular ubicación: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificación de pantalla inalámbrica"</string>
- <string name="wifi_verbose_logging" msgid="4203729756047242344">"Habilitar registro Wi-Fi detallado"</string>
+ <string name="wifi_verbose_logging" msgid="4203729756047242344">"Habilitar registro de Wi-Fi detallado"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activos"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración por hardware para conexión compartida"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sin nombre"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inhabilitar volumen absoluto"</string>
- <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión AVRCP del Bluetooth"</string>
- <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona la versión AVRCP del Bluetooth"</string>
+ <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión AVRCP de Bluetooth"</string>
+ <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona la versión AVRCP de Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec de audio de Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="8436224899475822557">"Activar el códec de audio por Bluetooth\nSelección"</string>
- <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Frecuencia de muestreo de audio por Bluetooth"</string>
+ <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Frecuencia de muestreo de audio de Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Activar el códec de audio por Bluetooth\nSelección: frecuencia de muestreo"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits por muestra del audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="8063859754619484760">"Activar el códec de audio por Bluetooth\nSelección: bits por muestra"</string>
- <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modo de canal de audio por Bluetooth"</string>
+ <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modo de canal de audio de Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="7234956835280563341">"Activar el códec de audio por Bluetooth\nSelección: modo de canal"</string>
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Códec de audio LDAC de Bluetooth: calidad de reproducción"</string>
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Activar LDAC de audio por Bluetooth\nSelección de códec: calidad de reproducción"</string>
@@ -244,21 +245,21 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce el host del proveedor de DNS"</string>
<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_verbose_logging_summary" msgid="6615071616111731958">"Aumentar el nivel de registro de Wi-Fi y mostrar por SSID RSSI en el selector Wi-Fi"</string>
<string name="wifi_metered_label" msgid="4514924227256839725">"Medida"</string>
<string name="wifi_unmetered_label" msgid="6124098729457992931">"No medida"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños del búfer para registrar"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Elige el tamaño del Logger por búfer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"¿Borrar almacenamiento continuo del registrador?"</string>
<string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Cuando ya no supervisamos la actividad con el registrador de forma continua, estamos obligados a borrar los datos del registrador almacenados en el dispositivo."</string>
- <string name="select_logpersist_title" msgid="7530031344550073166">"Guardar datos de registro de forma continua"</string>
+ <string name="select_logpersist_title" msgid="7530031344550073166">"Guardar datos de registro continuamente"</string>
<string name="select_logpersist_dialog_title" msgid="4003400579973269060">"Seleccionar búferes de registro para guardarlos de forma continua en dispositivo"</string>
<string name="select_usb_configuration_title" msgid="2649938511506971843">"Seleccionar configuración de USB"</string>
<string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"Seleccionar configuración de USB"</string>
<string name="allow_mock_location" msgid="2787962564578664888">"Ubicaciones simuladas"</string>
<string name="allow_mock_location_summary" msgid="317615105156345626">"Permitir ubicaciones simuladas"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"Inspección de atributos de vista"</string>
- <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Mantener los datos móviles siempre activos, aunque la conexión Wi‑Fi esté activada (para cambiar de red rápidamente)"</string>
+ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Mantener los datos móviles siempre activos aunque la conexión Wi‑Fi esté activada (para cambiar de red rápidamente)"</string>
<string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Usar la conexión compartida con aceleración por hardware si está disponible"</string>
<string name="adb_warning_title" msgid="6234463310896563253">"¿Permitir depuración por USB?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"La depuración por USB solo está indicada para actividades de desarrollo. Puedes utilizarla para intercambiar datos entre el ordenador y el dispositivo, para instalar aplicaciones en el dispositivo sin recibir notificaciones y para leer datos de registro."</string>
@@ -274,13 +275,13 @@
<string name="hdcp_checking_title" msgid="8605478913544273282">"Comprobación de HDCP"</string>
<string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Establecer comprobación HDCP"</string>
<string name="debug_debugging_category" msgid="6781250159513471316">"Depuración"</string>
- <string name="debug_app" msgid="8349591734751384446">"Aplicación para depurar"</string>
+ <string name="debug_app" msgid="8349591734751384446">"Elegir aplicación de depuración"</string>
<string name="debug_app_not_set" msgid="718752499586403499">"Aplicación de depuración no configurada"</string>
<string name="debug_app_set" msgid="2063077997870280017">"Aplicación de depuración: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"Selecciona una aplicación"</string>
<string name="no_application" msgid="2813387563129153880">"Ninguna"</string>
<string name="wait_for_debugger" msgid="1202370874528893091">"Esperar al depurador"</string>
- <string name="wait_for_debugger_summary" msgid="1766918303462746804">"La aplicación depurada espera a que se active el depurador para ejecutarse"</string>
+ <string name="wait_for_debugger_summary" msgid="1766918303462746804">"La aplicación depurada espera a que se active el depurador antes de ejecutarse"</string>
<string name="debug_input_category" msgid="1811069939601180246">"Entrada"</string>
<string name="debug_drawing_category" msgid="6755716469267367852">"Dibujo"</string>
<string name="debug_hw_drawing_category" msgid="6220174216912308658">"Renderización acelerada por hardware"</string>
@@ -292,15 +293,15 @@
<string name="pointer_location_summary" msgid="840819275172753713">"Superponer los datos de las pulsaciones en la pantalla"</string>
<string name="show_touches" msgid="2642976305235070316">"Mostrar toques"</string>
<string name="show_touches_summary" msgid="6101183132903926324">"Mostrar la ubicación de los toques en la pantalla"</string>
- <string name="show_screen_updates" msgid="5470814345876056420">"Cambios de superficie"</string>
- <string name="show_screen_updates_summary" msgid="2569622766672785529">"Actualizar superficies de ventana al actualizarse"</string>
+ <string name="show_screen_updates" msgid="5470814345876056420">"Mostrar cambios de superficies"</string>
+ <string name="show_screen_updates_summary" msgid="2569622766672785529">"Parpadear todas las superficies de la ventana cuando se actualizan"</string>
<string name="show_hw_screen_updates" msgid="4117270979975470789">"Ver cambios de vista"</string>
- <string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Actualizar vistas de las ventanas creadas"</string>
+ <string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Parpadear vistas dentro de las ventanas cuando se dibujan"</string>
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Ver actualizaciones de capas de hardware"</string>
- <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Iluminar capas de hardware en verde al actualizarse"</string>
+ <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Parpadear capas de hardware en verde al actualizarse"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar sobredibujos de GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Inhabilitar superposiciones de hardware"</string>
- <string name="disable_overlays_summary" msgid="3578941133710758592">"Usar siempre la GPU para combinar pantallas"</string>
+ <string name="disable_overlays_summary" msgid="3578941133710758592">"Usar siempre la GPU para componer pantallas"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simular espacio de color"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"Habilitar seguimiento OpenGL"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"Inhabilitar enrutamiento de audio por USB"</string>
@@ -313,10 +314,10 @@
<string name="force_msaa_summary" msgid="9123553203895817537">"Habilitar MSAA 4x en aplicaciones de OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"Depurar operaciones de recorte no rectangulares"</string>
<string name="track_frame_time" msgid="6094365083096851167">"Trazar la renderización de HWUI"</string>
- <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Activar capas depuración GPU"</string>
- <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Permitir cargar capas de depuración de GPU en apps"</string>
+ <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Activar capas de depuración de GPU"</string>
+ <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Permitir cargar capas de depuración de GPU en aplicaciones"</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Escala de animación de ventana"</string>
- <string name="transition_animation_scale_title" msgid="387527540523595875">"Escala de transición-animación"</string>
+ <string name="transition_animation_scale_title" msgid="387527540523595875">"Escala de animación de transición"</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"Escala de duración de animación"</string>
<string name="overlay_display_devices_title" msgid="5364176287998398539">"Simular pantallas secundarias"</string>
<string name="debug_applications_category" msgid="4206913653849771549">"Aplicaciones"</string>
@@ -324,13 +325,13 @@
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Destruir actividades cuando el usuario deje de usarlas"</string>
<string name="app_process_limit_title" msgid="4280600650253107163">"Límitar procesos en segundo plano"</string>
<string name="show_all_anrs" msgid="4924885492787069007">"Mostrar ANR en segundo plano"</string>
- <string name="show_all_anrs_summary" msgid="6636514318275139826">"Mostrar el diálogo La aplicación no responde para aplicaciones en segundo plano"</string>
+ <string name="show_all_anrs_summary" msgid="6636514318275139826">"Mostrar el diálogo de que la aplicación no responde para aplicaciones en segundo plano"</string>
<string name="show_notification_channel_warnings" msgid="1399948193466922683">"Ver advertencias del canal de notificaciones"</string>
<string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Mostrar una advertencia en pantalla cuando una aplicación publica una notificación sin un canal válido"</string>
<string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permitir aplicaciones de forma externa"</string>
- <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Hacer que cualquier aplicación se pueda escribir en un dispositivo de almacenamiento externo, independientemente de los valores definidos"</string>
+ <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Hacer que cualquier aplicación se pueda escribir en un dispositivo de almacenamiento externo independientemente de los valores definidos"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forzar el ajuste de tamaño de las actividades"</string>
- <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Hacer que el tamaño de todas las actividades se pueda ajustar para el modo multiventana, independientemente de los valores definidos"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Hacer que el tamaño de todas las actividades se pueda ajustar para el modo multiventana independientemente de los valores definidos"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Habilitar ventanas de forma libre"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"Habilitar la opción para utilizar ventanas de forma libre experimentales"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Contraseña para copias de ordenador"</string>
@@ -354,8 +355,8 @@
<string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inactiva. Toca para alternar."</string>
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Activa. Toca para alternar."</string>
<string name="standby_bucket_summary" msgid="6567835350910684727">"Estado de la aplicación en espera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="runningservices_settings_title" msgid="8097287939865165213">"Servicios en uso"</string>
- <string name="runningservices_settings_summary" msgid="854608995821032748">"Ver y controlar los servicios en uso"</string>
+ <string name="runningservices_settings_title" msgid="8097287939865165213">"Servicios en ejecución"</string>
+ <string name="runningservices_settings_summary" msgid="854608995821032748">"Ver y controlar los servicios en ejecución"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Establecer implementación de WebView"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Esta opción ya no está disponible. Vuelve a intentarlo."</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 68b5227..e5e8f56 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Võrke ei saa kontrollida"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Puudub"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Salvestatud"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Pole ühendatud"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Keelatud"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP seadistamise ebaõnnestumine"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Võrgu kehva kvaliteedi tõttu ei ühendatud"</string>
@@ -87,7 +88,7 @@
<string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Kasutamine kontaktide jagamiseks"</string>
<string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"Interneti-ühenduse jagamine"</string>
<string name="bluetooth_profile_map" msgid="1019763341565580450">"Tekstsõnumid"</string>
- <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-kaardi juurdepääs"</string>
+ <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-i juurdepääs"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-heli: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-heli"</string>
<string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Kuuldeaparaadid"</string>
@@ -312,7 +313,7 @@
<string name="force_msaa" msgid="7920323238677284387">"Jõusta 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Luba 4x MSAA OpenGL ES 2.0 rakendustes"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"Silu mittetäisnurksed kärpimistoimingud"</string>
- <string name="track_frame_time" msgid="6094365083096851167">"Profiili HWUI renderdam."</string>
+ <string name="track_frame_time" msgid="6094365083096851167">"Profiili HWUI renderdamine"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"GPU silumise kihtide lubamine"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"GPU silumise kihtide laadimise lubamine silumisrakendustele"</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Akna animatsioonimastaap"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index c8453da..447b738 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ezin dira sareak bilatu"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Bat ere ez"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Gordeta"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Deskonektatuta"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desgaituta"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ezin izan da konfiguratu IP helbidea"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ez dago konektatuta sarearen kalitate eskasagatik"</string>
@@ -206,7 +207,7 @@
<string name="bugreport_in_power" msgid="7923901846375587241">"Akatsen txostenerako lasterbidea"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Bateriaren menuan, erakutsi akatsen txostena sortzeko botoia"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Mantendu aktibo"</string>
- <string name="keep_screen_on_summary" msgid="2173114350754293009">"Pantaila ez da inoiz inaktibo ezarriko kargatu bitartean"</string>
+ <string name="keep_screen_on_summary" msgid="2173114350754293009">"Pantaila ez da ezarriko inoiz inaktibo kargatu bitartean"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"Gaitu Bluetooth HCI miatze-erregistroa"</string>
<string name="bt_hci_snoop_log_summary" msgid="8857606786588106495">"Hauteman Bluetooth paketeak (aktibatu edo desaktibatu Bluetooth konexioa ezarpena aldatu ostean)."</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM desblokeoa"</string>
@@ -245,7 +246,7 @@
<string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Ezin izan da konektatu"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Erakutsi hari gabe bistaratzeko ziurtagiriaren aukerak"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Erakutsi datu gehiago wifi-sareetan saioa hastean. Erakutsi sarearen identifikatzailea eta seinalearen indarra wifi-sareen hautagailuan."</string>
- <string name="wifi_metered_label" msgid="4514924227256839725">"Sare mugatua"</string>
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Sare neurtua"</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>
@@ -266,7 +267,7 @@
<string name="dev_settings_warning_title" msgid="7244607768088540165">"Baimendu garapenerako ezarpenak?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"Ezarpen hauek garapen-xedeetarako pentsatu dira soilik. Baliteke ezarpenen eraginez gailua matxuratzea edo funtzionamendu okerra izatea."</string>
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Egiaztatu USBko aplikazioak"</string>
- <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Egiaztatu ADB/ADT bidez instalatutako aplikazioak portaera kaltegarriak antzemateko."</string>
+ <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Egiaztatu ADB/ADT bidez instalatutako aplikazioak portaera kaltegarriak antzemateko"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth gailuak izenik gabe (MAC helbideak soilik) erakutsiko dira"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Bluetooth bidezko bolumen absolutuaren eginbidea desgaitu egiten du urruneko gailuetan arazoak hautematen badira; esaterako, bolumena ozenegia bada edo ezin bada kontrolatu"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Tokiko terminala"</string>
@@ -296,12 +297,12 @@
<string name="show_screen_updates_summary" msgid="2569622766672785529">"Distiratu leiho osoen azalak eguneratzen direnean"</string>
<string name="show_hw_screen_updates" msgid="4117270979975470789">"Erakutsi ikuspegi-aldaketak"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Nabarmendu leiho barruko ikuspegiak marraztean"</string>
- <string name="show_hw_layers_updates" msgid="5645728765605699821">"Hardware-geruzen eguneratzeak"</string>
+ <string name="show_hw_layers_updates" msgid="5645728765605699821">"Hardware-geruzen aldaketak"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Eguneratu bitartean, hardware-geruzak berdez"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Araztu GPU gainidazketa"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Desgaitu HW gainjartzeak"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Erabili beti GPU pantaila-muntaietarako"</string>
- <string name="simulate_color_space" msgid="6745847141353345872">"Simulatu kolore-espazioa"</string>
+ <string name="simulate_color_space" msgid="6745847141353345872">"Simulatu kolore-eremua"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"Gaitu OpenGL aztarnak"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"Desgaitu USB audio-bideratzea"</string>
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Desgaitu USB audio-gailuetara automatikoki bideratzea"</string>
@@ -313,8 +314,8 @@
<string name="force_msaa_summary" msgid="9123553203895817537">"Gaitu 4x MSAA, OpenGL ES 2.0 aplikazioetan"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"Araztu angeluzuzenak ez diren klip-eragiketak"</string>
<string name="track_frame_time" msgid="6094365083096851167">"Profilaren HWUI errendatzea"</string>
- <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Gaitu GPUaren arazte-geruzak"</string>
- <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Onartu GPUaren arazte-geruzak kargatzea arazte-aplikazioetarako"</string>
+ <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Gaitu GPUaren arazketa-geruzak"</string>
+ <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Eman GPUaren arazketa-geruzak kargatzeko baimena arazketa-aplikazioei"</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Leihoen animazio-eskala"</string>
<string name="transition_animation_scale_title" msgid="387527540523595875">"Trantsizioen animazio-eskala"</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"Animatzailearen iraupena"</string>
@@ -328,9 +329,9 @@
<string name="show_notification_channel_warnings" msgid="1399948193466922683">"Erakutsi jakinarazpenen kanalen abisuak"</string>
<string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Bistaratu abisuak aplikazioek baliozko kanalik gabeko jakinarazpenak argitaratzean"</string>
<string name="force_allow_on_external" msgid="3215759785081916381">"Behartu aplikazioak onartzea kanpoko memorian"</string>
- <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Aplikazioek kanpoko memorian idatz dezakete, manifestuaren balioak kontuan izan gabe"</string>
+ <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Aplikazioek kanpoko memorian idatz dezakete, ezarritako balioak kontuan izan gabe"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Behartu jardueren tamaina doitu ahal izatea"</string>
- <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Eman aukera jarduera guztien tamaina doitzeko, hainbat leihotan erabili ahal izan daitezen, manifestuan jartzen duena jartzen duela ere."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Eman aukera jarduera guztien tamaina doitzeko, hainbat leihotan erabili ahal izan daitezen, ezarritako balioak kontuan izan gabe"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Gaitu estilo libreko leihoak"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"Onartu estilo libreko leiho esperimentalak"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Babeskopien pasahitz lokala"</string>
@@ -427,7 +428,7 @@
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Handiena"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Pertsonalizatua (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menua"</string>
- <string name="retail_demo_reset_message" msgid="118771671364131297">"Idatzi pasahitza jatorrizko ezarpenak demo moduan berrezartzeko"</string>
+ <string name="retail_demo_reset_message" msgid="118771671364131297">"Idatzi pasahitza jatorrizko datuak demo moduan berrezartzeko"</string>
<string name="retail_demo_reset_next" msgid="8356731459226304963">"Hurrengoa"</string>
<string name="retail_demo_reset_title" msgid="696589204029930100">"Pasahitza behar da"</string>
<string name="active_input_method_subtypes" msgid="3596398805424733238">"Idazketa-metodo aktiboak"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 59a0f7e..c8f99a7 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"اسکن شبکهها امکانپذیر نیست"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"هیچکدام"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ذخیرهشده"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"اتصال قطع شد"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"غیرفعال شد"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"پیکربندی IP انجام نشد"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"اتصال ناموفق به دلیل شبکه با کیفیت پایین"</string>
@@ -265,8 +266,8 @@
<string name="adb_keys_warning_message" msgid="5659849457135841625">"دسترسی به اشکالزدایی USB از تمام رایانههایی که قبلاً مجاز دانستهاید لغو شود؟"</string>
<string name="dev_settings_warning_title" msgid="7244607768088540165">"تنظیمات برنامهنویسی مجاز باشد؟"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"این تنظیمات فقط برای برنامهنویسی در نظر گرفته شده است. ممکن است استفاده از این تنظیمات موجب خرابی یا عملکرد نادرست دستگاه یا برنامههای شما شود."</string>
- <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"تأیید برنامههای نصب شده از طریق USB"</string>
- <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"برنامههای نصب شده از طریق ADB/ADT را ازنظر رفتار مخاطرهآمیز بررسی کنید."</string>
+ <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"تأیید برنامهها ازطریق USB"</string>
+ <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"برنامههای نصبشده ازطریق ADB/ADT را ازنظر رفتار مخاطرهآمیز بررسی کنید."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"دستگاههای بلوتوث بدون نام (فقط نشانیهای MAC) نشان داده خواهند شد"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"درصورت وجود مشکل در صدا با دستگاههای راه دور مثل صدای بلند ناخوشایند یا عدم کنترل صدا، ویژگی میزان صدای کامل بلوتوث را غیرفعال کنید."</string>
<string name="enable_terminal_title" msgid="95572094356054120">"ترمینال محلی"</string>
@@ -279,7 +280,7 @@
<string name="debug_app_set" msgid="2063077997870280017">"در حال اشکالزدایی برنامه: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"انتخاب برنامه"</string>
<string name="no_application" msgid="2813387563129153880">"هیچ چیز"</string>
- <string name="wait_for_debugger" msgid="1202370874528893091">"انتظار برای اشکالزدا"</string>
+ <string name="wait_for_debugger" msgid="1202370874528893091">"منتظر اشکالزدا"</string>
<string name="wait_for_debugger_summary" msgid="1766918303462746804">"برنامه اشکالزدایی شده منتظر پیوست شدن اشکالزدا قبل از اجرا است"</string>
<string name="debug_input_category" msgid="1811069939601180246">"ورودی"</string>
<string name="debug_drawing_category" msgid="6755716469267367852">"طراحی"</string>
@@ -307,8 +308,8 @@
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"غیرفعال کردن مسیریابی خودکار به وسایل جانبی صوتی USB"</string>
<string name="debug_layout" msgid="5981361776594526155">"نمایش محدودههای طرحبندی"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"نمایش مرزها، حاشیهها و ویژگیهای دیگر کلیپ."</string>
- <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"اجباری کردن چیدمان RTL"</string>
- <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"اجباری کردن چیدمان RTL صفحه برای همه زبانها"</string>
+ <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"اجباری کردن چیدمان راستچین"</string>
+ <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"اجباری کردن چیدمان راستچین صفحه برای همه زبانها"</string>
<string name="force_msaa" msgid="7920323238677284387">"اجبار 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"فعال کردن 4X MSAA در برنامههای OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"اشکالزدایی عملکردهای کلیپ غیرمربعی"</string>
@@ -323,12 +324,12 @@
<string name="immediately_destroy_activities" msgid="1579659389568133959">"فعالیتها نگه داشته نشوند"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"از بین بردن هر فعالیت به محض خروج کاربر از آن"</string>
<string name="app_process_limit_title" msgid="4280600650253107163">"محدودیت پردازش در پسزمینه"</string>
- <string name="show_all_anrs" msgid="4924885492787069007">"نمایش موارد ANR پسزمینه"</string>
+ <string name="show_all_anrs" msgid="4924885492787069007">"نمایش موارد «برنامه پاسخ نمیدهد» پسزمینه"</string>
<string name="show_all_anrs_summary" msgid="6636514318275139826">"نمایش گفتگوی \"برنامه پاسخ نمیدهد\" برای برنامههای پسزمینه"</string>
<string name="show_notification_channel_warnings" msgid="1399948193466922683">"نمایش هشدارهای کانال اعلان"</string>
<string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"هنگامی که برنامهای بدون وجود کانالی معتبر، اعلانی پست میکند، هشدار روی صفحهای نمایش میدهد"</string>
<string name="force_allow_on_external" msgid="3215759785081916381">"اجازه اجباری به برنامههای دستگاه ذخیره خارجی"</string>
- <string name="force_allow_on_external_summary" msgid="3640752408258034689">"بدون توجه به مقادیر مانیفست، هر برنامهای را برای نوشتن در حافظه خارجی واجد شرایط میکند"</string>
+ <string name="force_allow_on_external_summary" msgid="3640752408258034689">"بدون توجه به مقادیر آشکار، هر برنامهای را برای نوشتن در حافظه خارجی واجد شرایط میکند"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"اجبار فعالیتها به قابل تغییر اندازه بودن"</string>
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"بدون توجه به مقادیر مانیفست، اندازه همه فعالیتها برای حالت چند پنجرهای میتواند تغییر کند."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"فعال کردن پنجرههای آزاد"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 6ea317d..b166cb0 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Verkkoja ei voi etsiä."</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Ei mitään"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Tallennettu"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Yhteys katkaistu"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Pois käytöstä"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-kokoonpanovirhe"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ei yhteyttä – verkko huonolaatuinen"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index d7c8266..9983337 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossible de rechercher des réseaux."</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Aucune"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Enregistré"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Déconnecté"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Désactivés"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Échec de configuration de l\'adresse IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Non connecté en raison de la mauvaise qualité du réseau"</string>
@@ -318,7 +319,7 @@
<string name="window_animation_scale_title" msgid="6162587588166114700">"Échelle animation fenêtres"</string>
<string name="transition_animation_scale_title" msgid="387527540523595875">"Échelle animination transitions"</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"Échelle durée animation"</string>
- <string name="overlay_display_devices_title" msgid="5364176287998398539">"Simul. affich. secondaires"</string>
+ <string name="overlay_display_devices_title" msgid="5364176287998398539">"Simuler affich. secondaires"</string>
<string name="debug_applications_category" msgid="4206913653849771549">"Applications"</string>
<string name="immediately_destroy_activities" msgid="1579659389568133959">"Ne pas conserver activités"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Supprimer immédiatement les activités abandonnées"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 6aafcc3..e2bc2fe 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossible de rechercher des réseaux."</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Aucune"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Enregistré"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Déconnecté"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Désactivé"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Échec de configuration de l\'adresse IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Non connecté en raison de la faible qualité du réseau"</string>
@@ -206,7 +207,7 @@
<string name="bugreport_in_power" msgid="7923901846375587241">"Raccourci vers rapport de bug"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Afficher un bouton dans le menu de démarrage permettant de créer un rapport de bug"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Écran toujours actif"</string>
- <string name="keep_screen_on_summary" msgid="2173114350754293009">"L\'écran ne se met jamais en veille lorsqu\'il est en charge"</string>
+ <string name="keep_screen_on_summary" msgid="2173114350754293009">"L\'écran ne se met jamais en veille lorsque l\'appareil est en charge"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"Activer journaux HCI Bluetooth"</string>
<string name="bt_hci_snoop_log_summary" msgid="8857606786588106495">"Capturer les paquets Bluetooth. (Activer/Désactiver le Bluetooth après avoir modifié ce paramètre)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"Déverrouillage OEM"</string>
@@ -274,8 +275,8 @@
<string name="hdcp_checking_title" msgid="8605478913544273282">"Vérification HDCP"</string>
<string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Config. vérification HDCP"</string>
<string name="debug_debugging_category" msgid="6781250159513471316">"Débogage"</string>
- <string name="debug_app" msgid="8349591734751384446">"Sélectionner une application à déboguer"</string>
- <string name="debug_app_not_set" msgid="718752499586403499">"Aucune application à déboguer définie"</string>
+ <string name="debug_app" msgid="8349591734751384446">"Sélectionner une application de débogage"</string>
+ <string name="debug_app_not_set" msgid="718752499586403499">"Aucune application de débogage définie"</string>
<string name="debug_app_set" msgid="2063077997870280017">"Application à déboguer : <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"Sélectionner une appli"</string>
<string name="no_application" msgid="2813387563129153880">"Aucune"</string>
@@ -406,7 +407,7 @@
<string name="battery_info_status_charging_lower" msgid="8689770213898117994">"chargement…"</string>
<string name="battery_info_status_discharging" msgid="310932812698268588">"Pas en charge"</string>
<string name="battery_info_status_not_charging" msgid="8523453668342598579">"Appareil branché, mais impossible de le charger pour le moment"</string>
- <string name="battery_info_status_full" msgid="2824614753861462808">"pleine"</string>
+ <string name="battery_info_status_full" msgid="2824614753861462808">"Pleine"</string>
<string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Contrôlé par l\'administrateur"</string>
<string name="disabled" msgid="9206776641295849915">"Désactivée"</string>
<string name="external_source_trusted" msgid="2707996266575928037">"Autorisé"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 68b34ae..f41be39 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Non se poden explorar redes"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Ningunha"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Gardada"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Rede desconectada"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desactivadas"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Erro na configuración de IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Non se estableceu conexión porque a rede é de baixa calidade"</string>
@@ -34,7 +35,7 @@
<string name="wifi_not_in_range" msgid="1136191511238508967">"Non está dentro da zona de cobertura"</string>
<string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Non se conectará automaticamente"</string>
<string name="wifi_no_internet" msgid="4663834955626848401">"Sen acceso a Internet"</string>
- <string name="saved_network" msgid="4352716707126620811">"Redes gardadas por <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="saved_network" msgid="4352716707126620811">"Gardada por <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="connected_via_network_scorer" msgid="5713793306870815341">"Conectouse automaticamente a través de %1$s"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Conectada automaticamente a través dun provedor de valoración de rede"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado a través de %1$s"</string>
@@ -152,7 +153,7 @@
<string name="launch_defaults_some" msgid="313159469856372621">"Definíronse algúns valores predeterminados"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Non se definiu ningún valor predeterminado"</string>
<string name="tts_settings" msgid="8186971894801348327">"Configuración da síntese de voz"</string>
- <string name="tts_settings_title" msgid="1237820681016639683">"Síntese de voz"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Saída da síntese de voz"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidade da fala"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade á que se di o texto"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"Ton"</string>
@@ -166,7 +167,7 @@
<string name="tts_install_data_title" msgid="4264378440508149986">"Instalar datos de voz"</string>
<string name="tts_install_data_summary" msgid="5742135732511822589">"Instala os datos de voz necesarios para a síntese de voz"</string>
<string name="tts_engine_security_warning" msgid="8786238102020223650">"É posible que este motor de síntese de voz poida recompilar todo o texto falado, incluídos datos persoais como contrasinais e números de tarxetas de crédito. Provén do motor <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Queres activar o uso deste motor de síntese de voz?"</string>
- <string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma precisa dispoñer dunha conexión de rede que funcione para emitir a síntese de voz."</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma precisa dispoñer dunha conexión de rede que funcione para a saída da síntese de voz."</string>
<string name="tts_default_sample_string" msgid="4040835213373086322">"Este é un exemplo da síntese de voz"</string>
<string name="tts_status_title" msgid="7268566550242584413">"Estado do idioma predeterminado"</string>
<string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> é completamente compatible"</string>
@@ -227,8 +228,8 @@
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona a versión de Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec de audio por Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="8436224899475822557">"Activar códec de audio por Bluetooth\nSelección"</string>
- <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Taxa de mostraxe de audio por Bluetooth"</string>
- <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Activar códec de audio por Bluetooth\nSelección: taxa de mostraxe"</string>
+ <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Taxa de mostra de audio por Bluetooth"</string>
+ <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Activar códec de audio por Bluetooth\nSelección: taxa de mostra"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits por mostra de audio por Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="8063859754619484760">"Activar códec de audio por Bluetooth\nSelección: bits por mostra"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modo de canle de audio por Bluetooth"</string>
@@ -247,11 +248,11 @@
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumenta o nivel de rexistro da wifi, móstrao por SSID RSSI no selector de wifi"</string>
<string name="wifi_metered_label" msgid="4514924227256839725">"Sen tarifa plana"</string>
<string name="wifi_unmetered_label" msgid="6124098729457992931">"Con tarifa plana"</string>
- <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños do búfer do rexistrador"</string>
+ <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaño dos búfers do rexistrador"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Seleccionar tamaño do rexistrador por búfer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Queres borrar o almacenamento persistente do rexistrador?"</string>
<string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Cando xa non se supervisa a actividade co rexistrador de forma persistente, debemos borrar os datos do rexistrador almacenados no dispositivo."</string>
- <string name="select_logpersist_title" msgid="7530031344550073166">"Gardar datos do rexistrador de forma persistente"</string>
+ <string name="select_logpersist_title" msgid="7530031344550073166">"Almacenar de forma persistente"</string>
<string name="select_logpersist_dialog_title" msgid="4003400579973269060">"Seleccionar búfers de rexistro para gardalos de forma continua no dispositivo"</string>
<string name="select_usb_configuration_title" msgid="2649938511506971843">"Seleccionar configuración USB"</string>
<string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"Seleccionar configuración USB"</string>
@@ -266,9 +267,9 @@
<string name="dev_settings_warning_title" msgid="7244607768088540165">"Permitir a configuración de programación?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"Esta configuración só está destinada á programación. Esta pode provocar que o dispositivo e as aplicacións fallen ou se comporten incorrectamente."</string>
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar aplicacións por USB"</string>
- <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comproba as aplicacións instaladas a través de ADB/ADT para detectar comportamento perigoso."</string>
+ <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comproba as aplicacións instaladas a través de ADB/ADT para detectar comportamento perigoso"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Mostraranse dispositivos Bluetooth sen nomes (só enderezos MAC)"</string>
- <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desactiva a función do volume absoluto do Bluetooth en caso de que se produzan problemas de volume cos dispositivos remotos, como volume demasiado alto ou falta de control."</string>
+ <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desactiva a función do volume absoluto do Bluetooth en caso de que se produzan problemas de volume cos dispositivos remotos, como volume demasiado alto ou falta de control"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Activa a aplicación terminal que ofrece acceso ao shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Comprobación HDCP"</string>
@@ -301,7 +302,7 @@
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar superposición GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Desactivar superposicións de hardware"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Utiliza sempre GPU para a composición da pantalla"</string>
- <string name="simulate_color_space" msgid="6745847141353345872">"Simular o espazo da cor"</string>
+ <string name="simulate_color_space" msgid="6745847141353345872">"Simular espazo de cor"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"Activar rastros OpenGL"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"Desactivar encamiñamento audio USB"</string>
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Desactiva o encamiñamento automático a periféricos de audio USB"</string>
@@ -321,8 +322,8 @@
<string name="overlay_display_devices_title" msgid="5364176287998398539">"Simular pantallas secundarias"</string>
<string name="debug_applications_category" msgid="4206913653849771549">"Aplicacións"</string>
<string name="immediately_destroy_activities" msgid="1579659389568133959">"Non manter actividades"</string>
- <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Destruír actividades cando o usuario non as use"</string>
- <string name="app_process_limit_title" msgid="4280600650253107163">"Límite procesos 2º plano"</string>
+ <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Destrúe as actividades cando o usuario non as usa"</string>
+ <string name="app_process_limit_title" msgid="4280600650253107163">"Limitar procesos en segundo plano"</string>
<string name="show_all_anrs" msgid="4924885492787069007">"Erros sen resposta en segundo plano"</string>
<string name="show_all_anrs_summary" msgid="6636514318275139826">"Indica que unha aplicación en segundo plano non responde"</string>
<string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostrar avisos de notificacións"</string>
@@ -332,7 +333,7 @@
<string name="force_resizable_activities" msgid="8615764378147824985">"Forzar o axuste do tamaño das actividades"</string>
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permite axustar o tamaño de todas as actividades para o modo multiventá, independentemente dos valores do manifesto"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Activar ventás de forma libre"</string>
- <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa a compatibilidade con ventás de forma libre experimentais."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa a compatibilidade con ventás de forma libre experimentais"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Contrasinal para copias"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"As copias de seguranza de ordenador completas non están protexidas"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toca para cambiar ou eliminar o contrasinal para as copias de seguranza completas de ordenador"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index de70b60..a411a05 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"નેટવર્ક્સ માટે સ્કૅન કરી શકતા નથી"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"કોઈ નહીં"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"સાચવેલા"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"ડિસ્કનેક્ટ કર્યું"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"અક્ષમ કર્યો"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP કન્ફિગરેશન નિષ્ફળ"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ઓછી ગુણવત્તાવાળા નેટવર્કના લીધે કનેક્ટ થયું નથી"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 416c948..954c04a 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"नेटवर्क के लिए स्कैन नहीं कर सकता"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"कोई नहीं"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"सेव किया गया"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"डिसकनेक्ट किया गया"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"अक्षम"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP कॉन्फ़िगरेशन की विफलता"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"खराब नेटवर्क होने के कारण कनेक्ट नहीं हुआ"</string>
@@ -137,15 +138,15 @@
<string name="accessibility_wifi_security_type_none" msgid="1223747559986205423">"खुला नेटवर्क"</string>
<string name="accessibility_wifi_security_type_secured" msgid="862921720418885331">"सुरक्षित नेटवर्क"</string>
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
- <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"निकाले गए ऐप्स"</string>
- <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ऐप्स और उपयोगकर्ताओं को निकालें"</string>
+ <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"निकाले गए ऐप्लिकेशन"</string>
+ <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ऐप्लिकेशन और उपयोगकर्ताओं को निकालें"</string>
<string name="data_usage_ota" msgid="5377889154805560860">"सिस्टम अपडेट"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"यूएसबी से टेदरिंग"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हॉटस्पॉट"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लूटूथ टेदरिंग"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"टेदरिंग"</string>
<string name="tether_settings_title_all" msgid="8356136101061143841">"टेदरिंग और पोर्टेबल हॉटस्पॉट"</string>
- <string name="managed_user_title" msgid="8109605045406748842">"सभी कार्यस्थल ऐप्लिकेशन"</string>
+ <string name="managed_user_title" msgid="8109605045406748842">"सभी दफ़्तर ऐप्लिकेशन"</string>
<string name="user_guest" msgid="8475274842845401871">"मेहमान"</string>
<string name="unknown" msgid="1592123443519355854">"अज्ञात"</string>
<string name="running_process_item_user_label" msgid="3129887865552025943">"उपयोगकर्ता: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
@@ -165,7 +166,7 @@
<string name="tts_play_example_summary" msgid="8029071615047894486">"लिखे हुए को बोली में बदलने की सुविधा की एक छोटी सी झलक चलाएं"</string>
<string name="tts_install_data_title" msgid="4264378440508149986">"आवाज़ का डेटा इंस्टॉल करें"</string>
<string name="tts_install_data_summary" msgid="5742135732511822589">"बोली-संश्लेषण के लिए आवश्यक ध्वनि डेटा इंस्टॉल करें"</string>
- <string name="tts_engine_security_warning" msgid="8786238102020223650">"यह स्पीच सिंथेसिस (लिखे हुए को मशीन द्वारा बोली में बदलना) इंजन, पासवर्ड और क्रेडिट कार्ड नंबर जैसे निजी डेटा सहित आपके द्वारा बोले जाने वाले सभी लेख इकट्ठा कर सकता है. यह <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> इंजन से आता है. स्पीच सिंथेसिस इंजन के इस्तेमाल को चालू करें?"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"यह स्पीच सिंथेसिस (लिखे हुए को मशीन द्वारा बोली में बदलना) इंजन, पासवर्ड और क्रेडिट कार्ड नंबर जैसे निजी डेटा सहित बोले जाने वाले सभी लेख इकट्ठा कर सकता है. यह <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> इंजन से आता है. स्पीच सिंथेसिस इंजन के इस्तेमाल को चालू करें?"</string>
<string name="tts_engine_network_required" msgid="1190837151485314743">"लेख-से-बोली आउटपुट के लिए इस भाषा को क्रियाशील नेटवर्क कनेक्शन की आवश्यकता है."</string>
<string name="tts_default_sample_string" msgid="4040835213373086322">"यह बोली संश्लेषण का एक उदाहरण है"</string>
<string name="tts_status_title" msgid="7268566550242584413">"डिफ़ॉल्ट भाषा स्थिति"</string>
@@ -195,7 +196,7 @@
<string name="category_work" msgid="8699184680584175622">"कार्यालय"</string>
<string name="development_settings_title" msgid="215179176067683667">"डेवलपर के लिए सेटिंग और टूल"</string>
<string name="development_settings_enable" msgid="542530994778109538">"डेवलपर के लिए सेटिंग और टूल चालू करें"</string>
- <string name="development_settings_summary" msgid="1815795401632854041">"ऐप्स विकास के लिए विकल्प सेट करें"</string>
+ <string name="development_settings_summary" msgid="1815795401632854041">"ऐप्लिकेशन विकास के लिए विकल्प सेट करें"</string>
<string name="development_settings_not_available" msgid="4308569041701535607">"यह उपयोगकर्ता, डेवलपर के लिए सेटिंग और टूल का इस्तेमाल नहीं कर सकता"</string>
<string name="vpn_settings_not_available" msgid="956841430176985598">"VPN सेटिंग इस उपयोगकर्ता के लिए उपलब्ध नहीं हैं"</string>
<string name="tethering_settings_not_available" msgid="6765770438438291012">"टेदरिंग सेटिंग इस उपयोगकर्ता के लिए उपलब्ध नहीं हैं"</string>
@@ -264,7 +265,7 @@
<string name="adb_warning_message" msgid="7316799925425402244">"USB डीबग करने का मकसद केवल डेवेलप करना है. इसका इस्तेमाल आपके कंप्यूटर और आपके डिवाइस के बीच डेटा को कॉपी करने, बिना सूचना के आपके डिवाइस पर ऐप इंस्टॉल करने और लॉग डेटा पढ़ने के लिए करें."</string>
<string name="adb_keys_warning_message" msgid="5659849457135841625">"उन सभी कंप्यूटरों से USB डीबग करने की पहुंचर रद्द करें, जिन्हें आपने पहले इसकी मंज़ूरी दी थी?"</string>
<string name="dev_settings_warning_title" msgid="7244607768088540165">"विकास सेटिंग की अनुमति दें?"</string>
- <string name="dev_settings_warning_message" msgid="2298337781139097964">"ये सेटिंग केवल विकास संबंधी उपयोग के प्रयोजन से हैं. वे आपके डिवाइस और उस पर स्थित ऐप्स को खराब कर सकती हैं या उनके दुर्व्यवहार का कारण हो सकती हैं."</string>
+ <string name="dev_settings_warning_message" msgid="2298337781139097964">"ये सेटिंग केवल विकास संबंधी उपयोग के प्रयोजन से हैं. वे आपके डिवाइस और उस पर स्थित ऐप्लिकेशन को खराब कर सकती हैं या उनके दुर्व्यवहार का कारण हो सकती हैं."</string>
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"यूएसबी पर ऐप्लिकेशन की पुष्टि करें"</string>
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"नुकसानदेह व्यवहार के लिए ADB/ADT से इंस्टॉल किए गए ऐप्लिकेशन जाँचें."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"बिना नाम वाले ब्लूटूथ डिवाइस (केवल MAC पते वाले) दिखाए जाएंगे"</string>
@@ -276,8 +277,8 @@
<string name="debug_debugging_category" msgid="6781250159513471316">"डीबग करना"</string>
<string name="debug_app" msgid="8349591734751384446">"डीबग करने के लिए ऐप्लिकेशन चुनें"</string>
<string name="debug_app_not_set" msgid="718752499586403499">"डीबग करने के लिए कोई ऐप्लिकेशन सेट नहीं है"</string>
- <string name="debug_app_set" msgid="2063077997870280017">"डीबग करने वाला ऐप्स : <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="select_application" msgid="5156029161289091703">"ऐप्स को चुनें"</string>
+ <string name="debug_app_set" msgid="2063077997870280017">"डीबग करने वाला ऐप्लिकेशन : <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="select_application" msgid="5156029161289091703">"ऐप्लिकेशन को चुनें"</string>
<string name="no_application" msgid="2813387563129153880">"कुछ भी नहीं"</string>
<string name="wait_for_debugger" msgid="1202370874528893091">"डीबगर का इंतज़ार करें"</string>
<string name="wait_for_debugger_summary" msgid="1766918303462746804">"डीबग किया गया ऐप्लिकेशन प्रोसेस के पहले डीबगर के अटैच होने का इंतज़ार करता है"</string>
@@ -433,7 +434,7 @@
<string name="active_input_method_subtypes" msgid="3596398805424733238">"टाइप करने की सक्रीय पद्धतियां"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"सिस्टम की भाषाओं का उपयोग करें"</string>
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> के लिए सेटिंग खोलने में विफल रहा"</string>
- <string name="ime_security_warning" msgid="4135828934735934248">"यह इनपुट विधि, पासवर्ड और क्रेडिट कार्ड नंबर जैसे निजी डेटा सहित आपके द्वारा लिखे जाने वाले सभी लेख को एकत्र कर सकती है. यह <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ऐप्स से आती है. इस इनपुट विधि का उपयोग करें?"</string>
+ <string name="ime_security_warning" msgid="4135828934735934248">"यह इनपुट विधि, पासवर्ड और क्रेडिट कार्ड नंबर जैसे निजी डेटा सहित लिखे जाने वाले सभी लेख को एकत्र कर सकती है. यह <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ऐप्लिकेशन से आती है. इस इनपुट विधि का उपयोग करें?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"नोट: पुनः बूट करने के बाद, यह ऐप्लिकेशन तब तक शुरू नहीं हो सकता है जब तक कि आप अपना फ़ोन अनलॉक ना कर लें"</string>
<string name="ims_reg_title" msgid="7609782759207241443">"IMS रजिस्ट्रेशन की स्थिति"</string>
<string name="ims_reg_status_registered" msgid="933003316932739188">"रजिस्टर है"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 506c792b..ea4a688 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -23,10 +23,11 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Skeniranje mreža nije moguće"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Spremljeno"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Nije povezano"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Konfiguracija IP-a nije uspjela"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Niste povezani jer je mreža loše kvalitete"</string>
- <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Povezivanje s Wi-Fi-jem nije uspjelo"</string>
+ <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Povezivanje s Wi-Fijem nije uspjelo"</string>
<string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem u autentifikaciji"</string>
<string name="wifi_cant_connect" msgid="5410016875644565884">"Povezivanje nije uspjelo"</string>
<string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"Povezivanje s aplikacijom \"<xliff:g id="AP_NAME">%1$s</xliff:g>\" nije uspjelo"</string>
@@ -152,7 +153,7 @@
<string name="launch_defaults_some" msgid="313159469856372621">"Postavljene su neke zadane postavke"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nema zadanih postavki"</string>
<string name="tts_settings" msgid="8186971894801348327">"Postavke za tekst u govor"</string>
- <string name="tts_settings_title" msgid="1237820681016639683">"Pretvaranje teksta u govor"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Tekst u govor"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina kojom se izgovara tekst"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"Visina glasa"</string>
@@ -193,7 +194,7 @@
<string name="choose_profile" msgid="6921016979430278661">"Odabir profila"</string>
<string name="category_personal" msgid="1299663247844969448">"Osobno"</string>
<string name="category_work" msgid="8699184680584175622">"Posao"</string>
- <string name="development_settings_title" msgid="215179176067683667">"Opcije za razvojne programere"</string>
+ <string name="development_settings_title" msgid="215179176067683667">"Za razvojne programere"</string>
<string name="development_settings_enable" msgid="542530994778109538">"Omogući opcije za razvojne programere"</string>
<string name="development_settings_summary" msgid="1815795401632854041">"Postavljanje opcija za razvoj aplikacije"</string>
<string name="development_settings_not_available" msgid="4308569041701535607">"Opcije razvojnih programera nisu dostupne za ovog korisnika"</string>
@@ -243,7 +244,7 @@
<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>
<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_display_certification_summary" msgid="1155182309166746973">"Prikaz opcija 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_metered_label" msgid="4514924227256839725">"S ograničenim prometom"</string>
<string name="wifi_unmetered_label" msgid="6124098729457992931">"Bez ograničenja prometa"</string>
@@ -301,7 +302,7 @@
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Rješavanje GPU preklapanja"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Onemogući dijeljenje mem."</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Uvijek koristi GPU za slaganje zaslona"</string>
- <string name="simulate_color_space" msgid="6745847141353345872">"Simuliraj prostor boja"</string>
+ <string name="simulate_color_space" msgid="6745847141353345872">"Simulacija prostora boja"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"Omogući OpenGL praćenja"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"Onemogući USB audiousmj."</string>
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Onemogući aut. usmjeravanje na USB audioperiferiju"</string>
@@ -314,11 +315,11 @@
<string name="show_non_rect_clip" msgid="505954950474595172">"Otkloni pogreške operacija nepravokutnog isječka"</string>
<string name="track_frame_time" msgid="6094365083096851167">"Profil HWUI generiranja"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Omogući slojeve za otklanjanje pogrešaka GPU-a"</string>
- <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Omogući učitavanje slojeva za otklanjanje pogrešaka GPU-a za aplikacije za otklanjanje pogrešaka"</string>
+ <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Omogućite učitavanje slojeva za otklanjanje pogrešaka GPU-a za aplikacije za otklanjanje pogrešaka"</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Brzina animacije prozora"</string>
<string name="transition_animation_scale_title" msgid="387527540523595875">"Brzina animacije prijelaza"</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"Razmjer duljine animatora"</string>
- <string name="overlay_display_devices_title" msgid="5364176287998398539">"Simuliraj sekund. zaslone"</string>
+ <string name="overlay_display_devices_title" msgid="5364176287998398539">"Simulacija sek. zaslona"</string>
<string name="debug_applications_category" msgid="4206913653849771549">"Aplikacije"</string>
<string name="immediately_destroy_activities" msgid="1579659389568133959">"Uklanjanje aktivnosti"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Aktivnost se prekida čim je korisnik napusti."</string>
@@ -355,7 +356,7 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivno. Dodirnite da biste to promijenili."</string>
<string name="standby_bucket_summary" msgid="6567835350910684727">"Stanje aplikacije u mirovanju: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Pokrenute usluge"</string>
- <string name="runningservices_settings_summary" msgid="854608995821032748">"Pogledajte i nadzirite pokrenute procese"</string>
+ <string name="runningservices_settings_summary" msgid="854608995821032748">"Pregledajte i kontrolirajte pokrenute usluge"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacija WebViewa"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Postavi implementaciju WebViewa"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Taj izbor više nije važeći. Pokušajte ponovo."</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 39b0e2b..d4fc9a7 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nem lehet beolvasni a hálózatokat"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Nincs"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Mentve"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Leválasztva"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Letiltva"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurációs hiba"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nem kapcsolódik a hálózat rossz minősége miatt"</string>
@@ -203,7 +204,7 @@
<string name="enable_adb" msgid="7982306934419797485">"USB hibakeresés"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"Hibakeresés mód USB csatlakoztatásakor"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"USB-s hibakeresésre vonatkozó engedélyek visszavonása"</string>
- <string name="bugreport_in_power" msgid="7923901846375587241">"Hibajelentési gomb"</string>
+ <string name="bugreport_in_power" msgid="7923901846375587241">"Hibabejelentési gomb"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Gomb megjelenítése a bekapcsolási menüben hibajelentés készítéséhez"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Nem kapcsolódik ki"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"A képernyő soha nem kapcsol ki töltés során"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 93169ae..836b70d 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Հնարավոր չէ սկանավորել ցանցերը"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Ոչ մեկը"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Պահված է"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Կապ չկա"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Անջատված"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP կարգավորման ձախողում"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Չի կապակցվել ցանցի թույլ ազդանշանի պատճառով"</string>
@@ -207,7 +208,7 @@
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Գործարկման ցանկում ցույց տալ կոճակը՝ վրիպակների հաղորդման համար"</string>
<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 snoop log-ը"</string>
+ <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Միացնել HCI մատյանի վարումը Bluetooth-ի համար"</string>
<string name="bt_hci_snoop_log_summary" msgid="8857606786588106495">"Պահել Bluetooth փաթեթները (այս կարգավորումը փոխելուց հետո անհրաժեշտ է վերագործարկել Bluetooth-ը)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM ապակողպում"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Թույլ տալ սկզբնաբեռնման բեռնիչի ապակողպումը"</string>
@@ -227,7 +228,7 @@
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Ընտրել Bluetooth AVRCP տարբերակը"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth աուդիո կոդեկ"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="8436224899475822557">"Գործարկել Bluetooth աուդիո կոդեկը\nԸնտրություն"</string>
- <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth աուդիոյի Ընդհատավորման հաճախականությունը"</string>
+ <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth աուդիոյի ընդհատավորման հաճախականությունը"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Գործարկել Bluetooth աուդիո կոդեկը\nԸնտրություն՝ ընդհատավորման հաճախականություն"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth աուդիո, բիթ / նմուշ"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="8063859754619484760">"Գործարկել Bluetooth աուդիո կոդեկը\nԸնտրություն՝ բիթ/նմուշ"</string>
@@ -243,7 +244,7 @@
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Մասնավոր DNS ծառայության մատակարարի խնամորդի անունը"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Մուտքագրեք DNS ծառայության մատակարարի խնամորդի անունը"</string>
<string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Չհաջողվեց միանալ"</string>
- <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ցույց տալ անլար էկրանի հավաստագրման ընտրանքները"</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_metered_label" msgid="4514924227256839725">"Վճարովի թրաֆիկ"</string>
<string name="wifi_unmetered_label" msgid="6124098729457992931">"Անսահմանափակ թրաֆիկ"</string>
@@ -293,11 +294,11 @@
<string name="show_touches" msgid="2642976305235070316">"Ցույց տալ հպումները"</string>
<string name="show_touches_summary" msgid="6101183132903926324">"Ցույց տալ հպումների տեսանելի արձագանքը"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"Ցույց տալ մակերեսի թարմացումները"</string>
- <string name="show_screen_updates_summary" msgid="2569622766672785529">"Թող պատուհանի ամբողջական մակերեսները առկայծեն, երբ թարմացվում են"</string>
+ <string name="show_screen_updates_summary" msgid="2569622766672785529">"Թարմացվելիս ընդգծել սարքաշարի ծածկույթները կանաչ գույնով"</string>
<string name="show_hw_screen_updates" msgid="4117270979975470789">"Ցուցադրել թարմացումները"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Լուսավորել պատուհանի թարմացված տարածքները"</string>
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Ցույց տալ սարքաշարի ծածկույթի թարմացումները"</string>
- <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Թող սարքաշարի ծածկույթները կանաչ գույնով առկայծեն, երբ թարմացվեն"</string>
+ <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Թարմացվելիս ընդգծել սարքաշարի ծածկույթները կանաչ գույնով"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Վրիպազերծել GPU գերազանցումները"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Կասեցնել HW վրադրումները"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Միշտ օգտագործել GPU-ն` էկրանի կազմման համար"</string>
@@ -354,8 +355,8 @@
<string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Ակտիվ չէ: Հպեք՝ փոխելու համար:"</string>
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Ակտիվ է: Հպեք՝ փոխելու համար:"</string>
<string name="standby_bucket_summary" msgid="6567835350910684727">"Հավելվածի սպասման կարգավիճակ՝ <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="runningservices_settings_title" msgid="8097287939865165213">"Աշխատեցվող ծառայություններ"</string>
- <string name="runningservices_settings_summary" msgid="854608995821032748">"Դիտել և վերահսկել ընթացիկ աշխատեցվող ծառայությունները"</string>
+ <string name="runningservices_settings_title" msgid="8097287939865165213">"Աշխատող ծառայություններ"</string>
+ <string name="runningservices_settings_summary" msgid="854608995821032748">"Դիտել և վերահսկել ընթացիկ աշխատող ծառայությունները"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ծառայություն"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ընտրեք WebView-ի իրականացումը"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Այս ընտրանքն այլևս վավեր չէ: Փորձեք նորից:"</string>
@@ -382,10 +383,10 @@
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) կբավարարի մոտ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>՝ կախված օգտագործման եղանակից"</string>
<!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
<skip />
- <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) պետք է, որ բավականացնի մոտ <xliff:g id="TIME">%1$s</xliff:g>՝ կախված օգտագործման եղանակից"</string>
- <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Լիցքը պետք է, որ բավականացնի մոտ <xliff:g id="TIME">%1$s</xliff:g>՝ կախված օգտագործման եղանակից"</string>
- <string name="power_discharge_by" msgid="6453537733650125582">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) պետք է, որ բավականացնի մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="power_discharge_by_only" msgid="107616694963545745">"Լիցքը պետք է, որ բավականացնի մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) պետք է որ բավականացնի մինչև <xliff:g id="TIME">%1$s</xliff:g>՝ կախված օգտագործումից"</string>
+ <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Լիցքը պետք է որ բավականացնի մինչև <xliff:g id="TIME">%1$s</xliff:g>՝ կախված օգտագործումից"</string>
+ <string name="power_discharge_by" msgid="6453537733650125582">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) պետք է որ բավականացնի մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only" msgid="107616694963545745">"Լիցքը պետք է որ բավականացնի մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="1372817269546888804">"Մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_suggestion_extend_battery" msgid="4401408879069551485">"Երկարացրեք մարտկոցի աշխատաժամանակը <xliff:g id="TIME">%1$s</xliff:g>-ից"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Մնացել է <xliff:g id="THRESHOLD">%1$s</xliff:g>-ից պակաս"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 50e305e..1b8304e 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tidak dapat memindai jaringan"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Tidak ada"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Disimpan"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Terputus"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Nonaktif"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Kegagalan Konfigurasi IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Tidak tersambung karena jaringan berkualitas rendah"</string>
@@ -219,7 +220,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Jaringan"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Sertifikasi layar nirkabel"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktifkan Pencatatan Log Panjang Wi-Fi"</string>
- <string name="mobile_data_always_on" msgid="8774857027458200434">"Data seluler selalu aktif"</string>
+ <string name="mobile_data_always_on" msgid="8774857027458200434">"Kuota selalu aktif"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Akselerasi hardware tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Tampilkan perangkat Bluetooth tanpa nama"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Nonaktifkan volume absolut"</string>
@@ -258,7 +259,7 @@
<string name="allow_mock_location" msgid="2787962564578664888">"Mengizinkan lokasi palsu"</string>
<string name="allow_mock_location_summary" msgid="317615105156345626">"Mengizinkan lokasi palsu"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"Aktifkan inspeksi atribut tampilan"</string>
- <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Selalu aktifkan data seluler, meski Wi-Fi aktif (agar jaringan beralih dengan cepat)."</string>
+ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Selalu aktifkan kuota, meski Wi-Fi aktif (agar jaringan beralih dengan cepat)."</string>
<string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Gunakan akselerasi hardware tethering jika tersedia"</string>
<string name="adb_warning_title" msgid="6234463310896563253">"Izinkan melakukan debug USB?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"Debugging USB dimaksudkan untuk tujuan pengembangan saja. Gunakan untuk menyalin data antara komputer dan perangkat Anda, memasang apl pada perangkat tanpa notifikasi, dan membaca data log."</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 935f0ea..8333a59 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ekki er hægt að leita að netum"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Ekkert"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Vistað"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Aftengt"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Óvirkt"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-stillingarvilla"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Tenging er ekki til staðar því nettengingin er léleg"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index fdd1b41..e1e06d2 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossibile cercare reti"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Nessuna"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Salvata"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Nessuna connessione"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disattivata"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Errore configurazione IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Impossibile connettersi a causa della bassa qualità della rete"</string>
@@ -218,7 +219,7 @@
<string name="mock_location_app_set" msgid="8966420655295102685">"App di posizione fittizia: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="7044075693643009662">"Reti"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificazione display wireless"</string>
- <string name="wifi_verbose_logging" msgid="4203729756047242344">"Attiva registrazione dettagliata Wi-Fi"</string>
+ <string name="wifi_verbose_logging" msgid="4203729756047242344">"Attiva logging dettagliato Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dati mobili sempre attivi"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering accelerazione hardware"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostra dispositivi Bluetooth senza nome"</string>
@@ -227,7 +228,7 @@
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Seleziona versione Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="8436224899475822557">"Attiva il codec audio Bluetooth\nSelezione"</string>
- <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Freq. di campionamento audio Bluetooth"</string>
+ <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Frequenza campionamento audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Attiva il codec audio Bluetooth\nSelezione: Frequenza di campionamento"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bit per campione dell\'audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="8063859754619484760">"Attiva il codec audio Bluetooth\nSelezione: bit per campione"</string>
@@ -244,11 +245,11 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Inserisci il nome host del provider DNS"</string>
<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_verbose_logging_summary" msgid="6615071616111731958">"Aumenta livello di logging Wi-Fi, mostra SSID RSSI nel selettore Wi-Fi"</string>
<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="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>
<string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Quando il monitoraggio tramite logger permanente viene interrotto, siamo obbligati a eliminare i dati del logger memorizzati sul dispositivo."</string>
<string name="select_logpersist_title" msgid="7530031344550073166">"Salva dati del logger in modo permanente"</string>
@@ -297,7 +298,7 @@
<string name="show_hw_screen_updates" msgid="4117270979975470789">"Aggiornam. visualizzazione"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Flash visualizzazioni dentro finestre se disegnate"</string>
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Aggiornam. livelli hardware"</string>
- <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Lampeggia verde se aggiornam. livelli hardware"</string>
+ <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Lampeggia in verde livelli hardware durante aggiornamento"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug overdraw GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Disabilita overlay HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Usa sempre GPU per la composizione dello schermo"</string>
@@ -314,7 +315,7 @@
<string name="show_non_rect_clip" msgid="505954950474595172">"Debug operazioni ritaglio non rettangolare"</string>
<string name="track_frame_time" msgid="6094365083096851167">"Rendering HWUI profilo"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Attiva livelli debug GPU"</string>
- <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Consenti caricamento livelli debug GPU app debug"</string>
+ <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Consenti caricamento livelli debug GPU per app di debug"</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Scala animazione finestra"</string>
<string name="transition_animation_scale_title" msgid="387527540523595875">"Scala animazione transizione"</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"Scala durata animatore"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 806efa7..9352479 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"לא ניתן לסרוק לאיתור רשתות"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"ללא"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"נשמר"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"מנותקת"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"מושבת"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"כשל בתצורת IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"אין חיבור לרשת, כי איכות הרשת נמוכה"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 26ec107..b032aad 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ネットワークをスキャンできません"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"なし"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"保存済み"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"未接続"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"無効"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP設定エラー"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ネットワークの品質が低いため、接続されていません"</string>
@@ -296,10 +297,10 @@
<string name="show_screen_updates_summary" msgid="2569622766672785529">"更新時にウィンドウの表示面全体を点滅させる"</string>
<string name="show_hw_screen_updates" msgid="4117270979975470789">"画面の更新を表示"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"描画時にウィンドウ内の表示を点滅させる"</string>
- <string name="show_hw_layers_updates" msgid="5645728765605699821">"ハードウェア層情報を表示"</string>
+ <string name="show_hw_layers_updates" msgid="5645728765605699821">"ハードウェア層の更新を表示"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ハードウェア層が更新されると緑色に点滅する"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPUオーバードローをデバッグ"</string>
- <string name="disable_overlays" msgid="2074488440505934665">"HWオーバーレイを無効"</string>
+ <string name="disable_overlays" msgid="2074488440505934665">"HWオーバーレイを無効化"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"画面合成に常にGPUを使用する"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"色空間シミュレート"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"OpenGLトレースを有効化"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 23cdb84..2c1d7c0 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ქსელების სკანირება არა არის შესაძლებელი"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"არცერთი"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"დამახსოვრებულია"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"კავშირი გაწყვეტილია"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"გამორთულია"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP კონფიგურაციის შეფერხება"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"არ არის დაკავშირებული დაბალი ხარისხის ქსელის გამო"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 8b128e5..5ae201e 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Желілерді шолу мүмкін емес"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Ешқандай"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Сақталды"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Ажыратылған"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Өшірілген"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурациясының қатесі"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Желі байланысының сапасы төмен болғандықтан қосылмады"</string>
@@ -220,7 +221,7 @@
<string name="wifi_display_certification" msgid="8611569543791307533">"Сымсыз дисплей сертификаты"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi егжей-тегжейлі журналы"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобильдік деректер әрқашан қосулы"</string>
- <string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингтің аппараттық жеделдетуі"</string>
+ <string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетеринг режиміндегі аппараттық жеделдету"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth құрылғыларын атаусыз көрсету"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Абсолютті дыбыс деңгейін өшіру"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP нұсқасы"</string>
@@ -259,7 +260,7 @@
<string name="allow_mock_location_summary" msgid="317615105156345626">"Жасанды аймақтарды пайдалануға рұқсат беру"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"Көру төлсипатын тексеруді қосу"</string>
<string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Wi‑Fi қосулы кезде де мобильдік интернетті өшірмеу (желіні жылдам ауыстыру үшін)"</string>
- <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Қолжетімді болса тетерингтің аппараттық жеделдетуін пайдалану"</string>
+ <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Тетеринг режиміндегі аппараттық жеделдетуді пайдалану (қолжетімді болса)"</string>
<string name="adb_warning_title" msgid="6234463310896563253">"USB жөндеулеріне рұқсат берілсін бе?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"USB жөндеу дамыту мақсаттарына ғана арналған. Оны компьютер және құрылғы арасында дерек көшіру, құрылғыға ескертусіз қолданба орнату және тіркелім деректерін оқу үшін қолданыңыз."</string>
<string name="adb_keys_warning_message" msgid="5659849457135841625">"Бұған дейін рұқсат берілген барлық компьютерлерде USB жөндеу функциясына тыйым салынсын ба?"</string>
@@ -283,7 +284,7 @@
<string name="wait_for_debugger_summary" msgid="1766918303462746804">"Орындау алдында жөнделетін қолданба жөндеушіні күтеді"</string>
<string name="debug_input_category" msgid="1811069939601180246">"Кіріс"</string>
<string name="debug_drawing_category" msgid="6755716469267367852">"Сызу"</string>
- <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Бейнелеуді жабдықпен жылдамдату"</string>
+ <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Бейнелеуді аппараттық жеделдету"</string>
<string name="media_category" msgid="4388305075496848353">"Meдиа"</string>
<string name="debug_monitoring_category" msgid="7640508148375798343">"Бақылау"</string>
<string name="strict_mode" msgid="1938795874357830695">"Қатаң режим қосылған"</string>
@@ -330,9 +331,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Сыртқы жадта қолданбаларға рұқсат ету"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"Манифест мәндеріне қарамастан, кез келген қолданбаны сыртқы жадқа жазу мүмкіндігін береді"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Әрекеттердің өлшемін өзгертуге рұқсат ету"</string>
- <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Манифест мәндеріне қарамастан бірнеше терезе режимінде барлық әрекеттердің өлшемін өзгертуге рұқсат беру."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Манифест мәндеріне қарамастан, бірнеше терезе режимінде барлық әрекеттердің өлшемін өзгертуге рұқсат беру"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Еркін пішіндегі терезелерді қосу"</string>
- <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Еркін пішінді терезелерді құру эксперименттік функиясын қосу."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Еркін пішінді терезелерді құру эксперименттік функиясын қосу"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Компьютердегі сақтық көшірме құпия сөзі"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Компьютердегі толық сақтық көшірмелер қазір қорғалмаған"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Үстелдік компьютердің толық сақтық көшірмелерінің кілтсөзін өзгерту немесе жою үшін түртіңіз"</string>
@@ -356,7 +357,7 @@
<string name="standby_bucket_summary" msgid="6567835350910684727">"Қолданбаның күту режимі: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Қосылып тұрған қызметтер"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Қазір істеп тұрған қызметтерді көру және басқару"</string>
- <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ендіру"</string>
+ <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView қызметі"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ендіруін орнату"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Бұл таңдау енді жарамды емес. Әрекетті қайталаңыз."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Файлды шифрлауға түрлендіру"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 6b89588..ed00b68 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"មិនអាចវិភាគរកបណ្ដាញ"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"គ្មាន"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"បានរក្សាទុក"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"បានផ្ដាច់"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"បានបិទ"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"ការកំណត់រចនាសម្ព័ន្ធ IP បរាជ័យ"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"មិនអាចភ្ជាប់បានទេ ដោយសារបណ្តាញមានគុណភាពសេវាខ្សោយ"</string>
@@ -152,7 +153,7 @@
<string name="launch_defaults_some" msgid="313159469856372621">"លំនាំដើមមួយចំនួនត្រូវបានកំណត់"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"គ្មានការកំណត់លំនាំដើម"</string>
<string name="tts_settings" msgid="8186971894801348327">"ការកំណត់អត្ថបទទៅជាកានិយាយ"</string>
- <string name="tts_settings_title" msgid="1237820681016639683">"លទ្ធផលសំឡេងអានអត្ថបទ"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"លទ្ធផលនៃការបំប្លែងអត្ថបទទៅជាការនិយាយ"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"អត្រានិយាយ"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ល្បឿនពេលអានអត្ថបទ"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"ឡើង-ចុះ"</string>
@@ -247,7 +248,7 @@
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"បង្កើនកម្រិតកំណត់ហេតុ Wi-Fi បង្ហាញក្នុង SSID RSSI ក្នុងកម្មវិធីជ្រើសរើស Wi-Fi"</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">"ទំហំ buffer របស់ Logger"</string>
+ <string name="select_logd_size_title" msgid="7433137108348553508">"ទំហំកន្លែងផ្ទុករបស់ 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>
<string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"នៅពេលដែលយើងឈប់ធ្វើការត្រួតពិនិត្យតទៅទៀតដោយប្រើ logger ដែលប្រើបានយូរ យើងត្រូវបានតម្រូវឲ្យលុបទិន្នន័យ logger ដែលមាននៅលើឧបករណ៍របស់អ្នក"</string>
@@ -258,7 +259,7 @@
<string name="allow_mock_location" msgid="2787962564578664888">"ឲ្យក្លែងទីតាំង"</string>
<string name="allow_mock_location_summary" msgid="317615105156345626">"អនុញ្ញាតទីតាំងក្លែងក្លាយ"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"បើកការត្រួតពិនិត្យគុណលក្ខណៈទិដ្ឋភាព"</string>
- <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"រក្សាទិន្នន័យចល័តឲ្យសកម្មជានិច្ច បើទោះបីជា Wi‑Fi សកម្មក៏ដោយ (សម្រាប់ការប្តូរបណ្តាញដែលមានល្បឿនលឿន)។"</string>
+ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"រក្សាទិន្នន័យទូរសព្ទចល័តឲ្យដំណើរការជានិច្ច ទោះបីជា Wi‑Fi ដំណើរការហើយក៏ដោយ (ដើម្បីប្តូរបណ្តាញឲ្យបានរហ័ស)។"</string>
<string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"ប្រើការបង្កើនល្បឿនផ្នែករឹងសម្រាប់ការភ្ជាប់ ប្រសិនបើអាចប្រើបាន"</string>
<string name="adb_warning_title" msgid="6234463310896563253">"អនុញ្ញាតការកែកំហុសតាម USB ឬ?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"ការកែកំហុសយូអេសប៊ីគឺសម្រាប់តែការអភិវឌ្ឍប៉ុណ្ណោះ។ ប្រើវាដើម្បីចម្លងទិន្នន័យរវាងកុំព្យូទ័រ និងឧបករណ៍របស់អ្នក ដំឡើងកម្មវិធីក្នុងឧបករណ៍របស់អ្នកដោយមិនជូនដំណឹង និងអានទិន្នន័យកំណត់ហេតុ។"</string>
@@ -293,7 +294,7 @@
<string name="show_touches" msgid="2642976305235070316">"បង្ហាញការចុច"</string>
<string name="show_touches_summary" msgid="6101183132903926324">"បង្ហាញដានចុច នៅពេលចុច"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"បង្ហាញបច្ចុប្បន្នភាពផ្ទៃ"</string>
- <string name="show_screen_updates_summary" msgid="2569622766672785529">"ផ្ទៃបង្អួចទាំងមូលបញ្ចេញពន្លឺពេលពួកវាធ្វើបច្ចុប្បន្នភាព"</string>
+ <string name="show_screen_updates_summary" msgid="2569622766672785529">"ផ្ទៃវីនដូទាំងមូលបាញ់ពន្លឺពេលពួកវាធ្វើបច្ចុប្បន្នភាព"</string>
<string name="show_hw_screen_updates" msgid="4117270979975470789">"បង្ហាញការធ្វើបច្ចុប្បន្នភាពនៃការមើល"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"ទិដ្ឋភាពបញ្ចេញពន្លឺភ្លឹបភ្លែតនៅក្នុងវិនដូនៅពេលគូរ"</string>
<string name="show_hw_layers_updates" msgid="5645728765605699821">"បង្ហាញបច្ចុប្បន្នភាពស្រទាប់ផ្នែករឹង"</string>
@@ -311,7 +312,7 @@
<string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"ប្តូរទិសប្លង់អេក្រង់ទៅជា RTL សម្រាប់គ្រប់ភាសាទាំងអស់"</string>
<string name="force_msaa" msgid="7920323238677284387">"បង្ខំ 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"បើក 4x MSAA ក្នុងកម្មវិធី OpenGL ES 2.0"</string>
- <string name="show_non_rect_clip" msgid="505954950474595172">"កែប្រតិបត្តិការស្រង់ non-rectangular"</string>
+ <string name="show_non_rect_clip" msgid="505954950474595172">"កែប្រតិបត្តិការផ្នែកដកចេញដែលមិនមានរាងចតុកោណកែង"</string>
<string name="track_frame_time" msgid="6094365083096851167">"ការបំប្លែងកម្រងព័ត៌មាន HWUI"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"បើកស្រទាប់ជួសជុល GPU"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"អនុញ្ញាតឱ្យផ្ទុកស្រទាប់ជួសជុល GPU សម្រាប់កម្មវិធីជួសជុល"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 2b83f83..59adfb7 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ನೆಟ್ವರ್ಕ್ಗಳಿಗಾಗಿ ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"ಯಾವುದೂ ಇಲ್ಲ"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ಉಳಿಸಲಾಗಿದೆ"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ಕಾನ್ಫಿಗರೇಶನ್ ವಿಫಲತೆ"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ಕಡಿಮೆ ಗುಣಮಟ್ಟದ ನೆಟ್ವರ್ಕ್ನಿಂದಾಗಿ ಸಂಪರ್ಕ ಸಾಧಿಸಿಲ್ಲ"</string>
@@ -268,7 +269,7 @@
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB ಮೂಲಕ ಆಪ್ ಪರಿಶೀಲಿಸಿ"</string>
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ಹಾನಿಮಾಡುವಂತಹ ವರ್ತನೆಗಾಗಿ ADB/ADT ಮೂಲಕ ಸ್ಥಾಪಿಸಲಾದ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"ಹೆಸರುಗಳಿಲ್ಲದ (ಕೇವಲ MAC ವಿಳಾಸಗಳು ಮಾತ್ರ) ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ಪ್ರದರ್ಶಿಸಲಾಗುತ್ತದೆ"</string>
- <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ರಿಮೋಟ್ ಸಾಧನಗಳೊಂದಿಗೆ ಒಪ್ಪಲಾಗದ ಜೋರಾದ ವಾಲ್ಯೂಮ್ ಅಥವಾ ನಿಯಂತ್ರಣದ ಕೊರತೆಯಂತಹ ವಾಲ್ಯೂಮ್ ಸಮಸ್ಯೆಗಳಂತಹ ಸಂದರ್ಭದಲ್ಲಿ ಬ್ಲೂಟೂತ್ ಸಂಪೂರ್ಣ ವಾಲ್ಯೂಮ್ ವೈಶಿಷ್ಟ್ಯವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಬಹುದು."</string>
+ <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ರಿಮೋಟ್ ಸಾಧನಗಳಲ್ಲಿ ಕಂಡುಬರುವ ಸ್ವೀಕಾರಾರ್ಹವಲ್ಲದ ಜೋರಾದ ವಾಲ್ಯೂಮ್ ಅಥವಾ ನಿಯಂತ್ರಣದ ಕೊರತೆಯಂತಹ ವಾಲ್ಯೂಮ್ ಸಮಸ್ಯೆಗಳಂತಹ ಸಂದರ್ಭದಲ್ಲಿ ಬ್ಲೂಟೂತ್ನ ನಿಚ್ಚಳ ವಾಲ್ಯೂಮ್ ವೈಶಿಷ್ಟ್ಯವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ."</string>
<string name="enable_terminal_title" msgid="95572094356054120">"ಸ್ಥಳೀಯ ಟರ್ಮಿನಲ್"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"ಸ್ಥಳೀಯ ಶೆಲ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸುವ ಟರ್ಮಿನಲ್ ಅಪ್ಲಿಕೇಶನ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP ಪರೀಕ್ಷಿಸುವಿಕೆ"</string>
@@ -294,7 +295,7 @@
<string name="show_touches_summary" msgid="6101183132903926324">"ಟ್ಯಾಪ್ಗಳಿಗೆ ದೃಶ್ಯ ಪ್ರತಿಕ್ರಿಯೆ ತೋರಿಸು"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"ಸರ್ಫೇಸ್ ಅಪ್ಡೇಟ್"</string>
<string name="show_screen_updates_summary" msgid="2569622766672785529">"ಅಪ್ಡೇಟ್ ಆಗುವಾಗ ವಿಂಡೋದ ಸರ್ಫೇಸ್ ಫ್ಲ್ಯಾಶ್ ಆಗುತ್ತದೆ"</string>
- <string name="show_hw_screen_updates" msgid="4117270979975470789">"ಅಪ್ಡೇಟ್ಗಳನ್ನು ವೀಕ್ಷಿಸಿ ತೋರಿಸಿ"</string>
+ <string name="show_hw_screen_updates" msgid="4117270979975470789">"\'ಅಪ್ಡೇಟ್ಗಳನ್ನು ವೀಕ್ಷಿಸಿ\' ತೋರಿಸಿ"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"ಡ್ರಾ ಮಾಡಿದಾಗ ವಿಂಡೊದಲ್ಲಿ ವೀಕ್ಷಣೆ ಫ್ಲ್ಯಾಶ್"</string>
<string name="show_hw_layers_updates" msgid="5645728765605699821">"ಹಾರ್ಡ್ವೇರ್ ಲೇಯರ್ ಅಪ್ಡೇಟ್"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ಅವುಗಳು ನವೀಕರಿಸಿದಾಗ ಹಾರ್ಡ್ವೇರ್ ಲೇಯರ್ಗಳು ಹಸಿರು ಫ್ಲ್ಯಾಶ್ ಆಗುತ್ತದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index b1b88f3..0ac0848 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"네트워크를 검색할 수 없습니다."</string>
<string name="wifi_security_none" msgid="7985461072596594400">"없음"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"저장됨"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"연결 끊김"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"사용 중지됨"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 설정 실패"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"저품질 네트워크로 인해 연결되지 않음"</string>
@@ -291,13 +292,13 @@
<string name="pointer_location" msgid="6084434787496938001">"포인터 위치"</string>
<string name="pointer_location_summary" msgid="840819275172753713">"현재 터치 데이터 오버레이 표시"</string>
<string name="show_touches" msgid="2642976305235070316">"탭한 항목 표시"</string>
- <string name="show_touches_summary" msgid="6101183132903926324">"탭한 항목에 대해 시각적인 의견 표시"</string>
+ <string name="show_touches_summary" msgid="6101183132903926324">"탭한 항목에 대해 시각적인 피드백 표시"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"표면 업데이트 표시"</string>
- <string name="show_screen_updates_summary" msgid="2569622766672785529">"전체 창 표면이 업데이트되었을 때 플래시 처리"</string>
- <string name="show_hw_screen_updates" msgid="4117270979975470789">"업데이트 보기 표시"</string>
- <string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"드로잉했을 때 창 내부 보기 플래시 처리"</string>
+ <string name="show_screen_updates_summary" msgid="2569622766672785529">"전체 창 화면이 업데이트되었을 때 플래시 처리"</string>
+ <string name="show_hw_screen_updates" msgid="4117270979975470789">"보기 업데이트 표시"</string>
+ <string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"드로잉했을 때 창 내부 보기 깜박이기"</string>
<string name="show_hw_layers_updates" msgid="5645728765605699821">"하드웨어 레이어 업데이트 표시"</string>
- <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"업데이트할 때 하드웨어 레이어 녹색으로 깜박이기"</string>
+ <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"하드웨어 레이어 업데이트 시 녹색으로 깜박이기"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU 오버드로 디버그"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW 오버레이 사용 안함"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"화면 합성 목적으로 항상 GPU 사용"</string>
@@ -451,7 +452,7 @@
<string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"켜기"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"방해 금지 모드 사용 설정"</string>
<string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"사용 안함"</string>
- <string name="zen_interruption_level_priority" msgid="2078370238113347720">"중요 알림만"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"중요 알림만 허용"</string>
<string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
<string name="zen_alarm_warning_indef" msgid="3007988140196673193">"그때까지 알림 일시중지 상태를 유지하면 <xliff:g id="WHEN">%1$s</xliff:g>에 다음 알람을 들을 수 없습니다."</string>
<string name="zen_alarm_warning" msgid="6236690803924413088">"<xliff:g id="WHEN">%1$s</xliff:g>에 다음 알람을 들을 수 없습니다."</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index e799d0c..4991ddb 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Түйүндөрдү издөө мүмкүн эмес"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Жок"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Сакталды"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Ажыратылды"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Өчүрүлгөн"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурациясы бузулду"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Тармактын сапаты начар болгондуктан туташкан жок"</string>
@@ -260,10 +261,10 @@
<string name="debug_view_attributes" msgid="6485448367803310384">"Аттрибуттарды текшерүүнү иштетүү"</string>
<string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Wi-Fi иштеп турганда да дайындар мобилдик тармак аркылуу өткөрүлө берет (бир тармактан экинчисине тезирээк которулуу үчүн)."</string>
<string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Мүмкүнчүлүккө жараша, модем режиминде аппарат тезирээк иштей баштайт"</string>
- <string name="adb_warning_title" msgid="6234463310896563253">"USB аркылуу жөндөөгө уруксат берилсинби?"</string>
+ <string name="adb_warning_title" msgid="6234463310896563253">"USB аркылуу жөндөөгө уруксат бересизби?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"USB-жөндөө - өндүрүү максатында гана түзүлгөн. Аны компүтериңиз менен түзмөгүңүздүн ортосунда берилиштерди алмашуу, түзмөгүңүзгө колдонмолорду эскертүүсүз орнотуу жана лог берилиштерин окуу үчүн колдонсоңуз болот."</string>
<string name="adb_keys_warning_message" msgid="5659849457135841625">"Сиз мурун USB жөндөөлөрүнө уруксат берген бардык компүтерлердин жеткиси жокко чыгарылсынбы?"</string>
- <string name="dev_settings_warning_title" msgid="7244607768088540165">"Өндүрүүчүнүн мүмкүнчүлүктөрүнө уруксат берилсинби?"</string>
+ <string name="dev_settings_warning_title" msgid="7244607768088540165">"Жөндөөлөрдү өзгөртүү"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"Бул орнотуулар өндүрүүчүлөр үчүн гана берилген. Булар түзмөгүңүздүн колдонмолорун бузулушуна же туура эмес иштешине алып келиши мүмкүн."</string>
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Орнотулуучу колдонмону текшерүү"</string>
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT аркылуу орнотулган колдонмолордун коопсуздугу текшерилет."</string>
@@ -451,7 +452,7 @@
<string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Күйгүзүү"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\"Тынчымды алба\" режимин күйгүзүү"</string>
<string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Эч качан"</string>
- <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Шашылыш эскертмелер гана"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Шашылыш билдирүүлөр гана"</string>
<string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
<string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Бул нерсе өчүрүлмөйүнчө <xliff:g id="WHEN">%1$s</xliff:g> боло турган кийинки ойготкучту укпайсыз"</string>
<string name="zen_alarm_warning" msgid="6236690803924413088">"<xliff:g id="WHEN">%1$s</xliff:g> боло турган кийинки ойготкучту укпайсыз"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 143b565..59ad7cc 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ບໍ່ສາມາດກວດຫາເຄືອຂ່າຍໄດ້"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"ບໍ່ໃຊ້"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ບັນທຶກແລ້ວ"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"ຕັດການເຊື່ອມຕໍ່ແລ້ວ"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ປິດການນຳໃຊ້"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"ການຕັ້ງຄ່າ IP ລົ້ມເຫຼວ"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ບໍ່ໄດ້ເຊື່ອມຕໍ່ເນື່ອງຈາກຄຸນນະພາບເຄືອຂ່າຍຕໍ່າ"</string>
@@ -265,8 +266,8 @@
<string name="adb_keys_warning_message" msgid="5659849457135841625">"ຖອດຖອນການເຂົ້າເຖິງການດີບັ໊ກຜ່ານ USB ຈາກຄອມພິວເຕີທຸກເຄື່ອງ ທີ່ທ່ານເຄີຍອະນຸຍາດກ່ອນໜ້ານີ້?"</string>
<string name="dev_settings_warning_title" msgid="7244607768088540165">"ອະນຸຍາດການຕັ້ງຄ່າສຳລັບນັກພັດທະນາ?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"ການຕັ້ງຄ່າເຫຼົ່ານີ້ແມ່ນມີຈຸດປະສົງເພື່ອການພັດທະນາເທົ່ານັ້ນ. ພວກມັນສາມາດເຮັດໃຫ້ອຸປະກອນ ແລະແອັບພລິເຄຊັນຂອງທ່ານຢຸດເຮັດວຽກ ຫຼືເຮັດວຽກຜິດປົກກະຕິໄດ້."</string>
- <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"ຢືນຢັນແອັບຯຜ່ານທາງ USB"</string>
- <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ກວດສອບແອັບຯທີ່ຕິດຕັ້ງແລ້ວຜ່ານທາງ ADB/ADT ເພື່ອກວດຫາພຶດຕິກຳທີ່ເປັນອັນຕະລາຍ."</string>
+ <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"ຢືນຢັນແອັບຜ່ານທາງ USB"</string>
+ <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ກວດສອບແອັບທີ່ຕິດຕັ້ງແລ້ວຜ່ານທາງ ADB/ADT ເພື່ອກວດຫາພຶດຕິກຳທີ່ເປັນອັນຕະລາຍ."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"ຈະສະແດງອຸປະກອນ Bluetooth ທີ່ບໍ່ມີຊື່ (ທີ່ຢູ່ MAC ເທົ່ານັ້ນ)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ປິດໃຊ້ຄຸນສົມບັດລະດັບສຽງສົມບູນຂອງ Bluetooth ໃນກໍລະນີເກີດບັນຫາລະດັບສຽງສົມບູນກັບອຸປະກອນທາງໄກ ເຊັ່ນວ່າ ລະດັບສຽງດັງເກີນຍອມຮັບໄດ້ ຫຼື ຄວບຄຸມບໍ່ໄດ້."</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal ໃນໂຕເຄື່ອງ"</string>
@@ -274,7 +275,7 @@
<string name="hdcp_checking_title" msgid="8605478913544273282">"ການກວດສອບ HDCP"</string>
<string name="hdcp_checking_dialog_title" msgid="5141305530923283">"ຕັ້ງວິທີການກວດສອບ HDCP"</string>
<string name="debug_debugging_category" msgid="6781250159513471316">"ການດີບັ໊ກ"</string>
- <string name="debug_app" msgid="8349591734751384446">"ເລືອກແອັບຯສຳລັບດີບັ໊ກ"</string>
+ <string name="debug_app" msgid="8349591734751384446">"ເລືອກແອັບສຳລັບດີບັ໊ກ"</string>
<string name="debug_app_not_set" msgid="718752499586403499">"ບໍ່ໄດ້ຕັ້ງການດີບັ໊ກແອັບພລິເຄຊັນ"</string>
<string name="debug_app_set" msgid="2063077997870280017">"ແອັບພລິເຄຊັນສຳລັບການດີບັ໊ກ: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"ເລືອກແອັບພລິເຄຊັນ"</string>
@@ -306,11 +307,11 @@
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"ປິດການນຳໃຊ້ເສັ້ນທາງສຽງ USB"</string>
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"ປິດການນຳໃຊ້ເສັ້ນທາງອັດຕະໂນມັດໄປຫາອຸປະກອນຕໍ່ພ່ວງສຽງ USB"</string>
<string name="debug_layout" msgid="5981361776594526155">"ສະແດງຂອບການຈັດວາງ"</string>
- <string name="debug_layout_summary" msgid="2001775315258637682">"ສະແດງໜ້າປົກຄລິບ, ຂອບ ແລະອື່ນໆ."</string>
+ <string name="debug_layout_summary" msgid="2001775315258637682">"ສະແດງໜ້າປົກຄລິບ, ຂອບ ແລະ ອື່ນໆ."</string>
<string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"ບັງຄັບໃຫ້ຮູບຮ່າງຂຽນຈາກຂວາຫາຊ້າຍ"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"ບັງຄັບໃຫ້ຮູບຮ່າງໜ້າຈໍ ຂຽນຈາກຂວາໄປຊ້າຍ ສຳລັບທຸກພາສາ"</string>
<string name="force_msaa" msgid="7920323238677284387">"ບັງຄັບໃຊ້ 4x MSAA"</string>
- <string name="force_msaa_summary" msgid="9123553203895817537">"ເປິດໃຊ້ 4x MSAA ໃນແອັບຯ OpenGL ES 2.0"</string>
+ <string name="force_msaa_summary" msgid="9123553203895817537">"ເປິດໃຊ້ 4x MSAA ໃນແອັບ OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"ດີບັ໊ກການເຮັດວຽກຂອງຄລິບທີ່ບໍ່ແມ່ນສີ່ຫຼ່ຽມ"</string>
<string name="track_frame_time" msgid="6094365083096851167">"ການປະມວນຜົນໂປຣໄຟລ໌ HWUI"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"ເປີດໃຊ້ຊັ້ນຂໍ້ມູນດີບັກ GPU"</string>
@@ -319,8 +320,8 @@
<string name="transition_animation_scale_title" msgid="387527540523595875">"ຂະໜາດອະນິເມຊັນ"</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"ໄລຍະເວລາອະນິເມຊັນ"</string>
<string name="overlay_display_devices_title" msgid="5364176287998398539">"ຈຳລອງຈໍສະແດງຜົນທີ່ສອງ"</string>
- <string name="debug_applications_category" msgid="4206913653849771549">"ແອັບຯ"</string>
- <string name="immediately_destroy_activities" msgid="1579659389568133959">"ບໍ່ຕ້ອງຮັກສາການເຮັດວຽກ"</string>
+ <string name="debug_applications_category" msgid="4206913653849771549">"ແອັບ"</string>
+ <string name="immediately_destroy_activities" msgid="1579659389568133959">"ບໍ່ຕ້ອງຮັກສາການເຄື່ອນໄຫວ"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"ລຶບທຸກການເຄື່ອນໄຫວທັນທີທີ່ຜູ້ໃຊ້ອອກຈາກມັນ"</string>
<string name="app_process_limit_title" msgid="4280600650253107163">"ການຈຳກັດໂປຣເຊສໃນພື້ນຫຼັງ"</string>
<string name="show_all_anrs" msgid="4924885492787069007">"ສະແດງ ANR ພື້ນຫຼັງ"</string>
@@ -329,11 +330,11 @@
<string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ສະແດງຄຳເຕືອນໃນໜ້າຈໍເມື່ອແອັບໂພສການແຈ້ງເຕືອນໂດຍບໍ່ມີຊ່ອງທີ່ຖືກຕ້ອງ"</string>
<string name="force_allow_on_external" msgid="3215759785081916381">"ບັງຄັບອະນຸຍາດແອັບຢູ່ພາຍນອກ"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"ເຮັດໃຫ້ທຸກແອັບມີສິດໄດ້ຮັບການຂຽນໃສ່ພື້ນທີ່ຈັດເກັບຂໍ້ມູນພາຍນອກ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest"</string>
- <string name="force_resizable_activities" msgid="8615764378147824985">"ບັງຄັງໃຫ້ກິດຈະກຳປ່ຽນຂະໜາດໄດ້"</string>
- <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ເຮັດໃຫ້ທຸກກິດຈະກຳສາມາດປັບຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຈໍ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest."</string>
- <string name="enable_freeform_support" msgid="1461893351278940416">"ເປີດໃຊ້ໜ້າຕ່າງຮູບແບບອິດສະຫຼະ"</string>
+ <string name="force_resizable_activities" msgid="8615764378147824985">"ບັງຄັງໃຫ້ການເຄື່ອນໄຫວປ່ຽນຂະໜາດໄດ້"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ເຮັດໃຫ້ທຸກການເຄື່ອນໄຫວສາມາດປັບຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຈໍ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest."</string>
+ <string name="enable_freeform_support" msgid="1461893351278940416">"ເປີດໃຊ້ໜ້າຈໍຮູບແບບອິດສະຫຼະ"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"ເປີດໃຊ້ການຮອງຮັບໜ້າຈໍຮູບແບບອິດສະຫຼະແບບທົດລອງ."</string>
- <string name="local_backup_password_title" msgid="3860471654439418822">"ລະຫັດຜ່ານການສຳຮອງຂໍ້ມູນເດັກສະທັອບ"</string>
+ <string name="local_backup_password_title" msgid="3860471654439418822">"ລະຫັດຜ່ານການສຳຮອງຂໍ້ມູນເດັສທັອບ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັສທັອບຍັງບໍ່ໄດ້ຮັບການປ້ອງກັນໃນເວລານີ້"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"ແຕະເພື່ອປ່ຽນ ຫຼື ລຶບລະຫັດຂອງການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັສທັອບ"</string>
<string name="local_backup_password_toast_success" msgid="582016086228434290">"ຕັ້ງລະຫັດສຳຮອງໃໝ່ແລ້ວ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 6cfa10c..bde71e3 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nepavyksta nuskaityti tinklų"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Nėra"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Išsaugotas"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Neprisijungta"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Neleidžiama"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfigūracijos triktis"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Neprisijungta dėl žemos kokybės tinklo"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index aac58d1d..5a1805a 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nevar skenēt tīklus"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Nav"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saglabāts"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Savienojums pārtraukts"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Atspējots"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfigurācijas kļūme"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Savienojums nav izveidots zemas kvalitātes tīkla dēļ"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 560843c..5be177d 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не може да скенира за мрежи"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Ниедна"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Зачувано"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Исклучен"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Оневозможено"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Конфигурирањето ИП не успеа"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Не е поврзано поради нискиот квалитет на мрежата"</string>
@@ -333,9 +334,9 @@
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"Направете сите активности да бидат со променлива големина за повеќе прозорци, без разлика на вредностите на манифестот."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Овозможи прозорци со слободна форма"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"Овозможи поддршка за експериментални прозорци со слободна форма."</string>
- <string name="local_backup_password_title" msgid="3860471654439418822">"Резервна лозинка за работна површина"</string>
- <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Целосни резервни копии на работната површина кои во моментов не се заштитени"</string>
- <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Допрете за да се промени или отстрани лозинката за целосни резервни копии на работната површина"</string>
+ <string name="local_backup_password_title" msgid="3860471654439418822">"Лозинка за бекап на компјутер"</string>
+ <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Целосниот бекап на компјутерот во моментов не е заштитен"</string>
+ <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Допрете за да се промени или отстрани лозинката за целосен бекап на компјутерот"</string>
<string name="local_backup_password_toast_success" msgid="582016086228434290">"Подесена нова лозинка на резервна копија"</string>
<string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"Новата лозинка и потврдата не се исти"</string>
<string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Неуспешно подесување лозинка на резервна копија"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index d9826ff..d3ebd99 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"നെറ്റ്വർക്കുകൾക്കായി സ്കാൻ ചെയ്യാനായില്ല"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"ഒന്നുമില്ല"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"സംരക്ഷിച്ചു"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"വിച്ഛേദിച്ചു"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP കോൺഫിഗറേഷൻ പരാജയം"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"മോശം നെറ്റ്വർക്ക് ആയതിനാൽ കണക്റ്റായില്ല"</string>
@@ -201,12 +202,12 @@
<string name="tethering_settings_not_available" msgid="6765770438438291012">"ഈ ഉപയോക്താവിനായി ടെതറിംഗ് ക്രമീകരണങ്ങൾ ലഭ്യമല്ല"</string>
<string name="apn_settings_not_available" msgid="7873729032165324000">"ആക്സസ്സ് പോയിന്റ് നെയിം ക്രമീകരണങ്ങൾ ഈ ഉപയോക്താവിനായി ലഭ്യമല്ല"</string>
<string name="enable_adb" msgid="7982306934419797485">"USB ഡീബഗ്ഗിംഗ്"</string>
- <string name="enable_adb_summary" msgid="4881186971746056635">"USB കണക്റ്റുചെയ്തിരിക്കുമ്പോൾ ഡീബഗ് മോഡ്"</string>
+ <string name="enable_adb_summary" msgid="4881186971746056635">"USB കണക്റ്റുചെയ്തിരിക്കുമ്പോഴുള്ള ഡീബഗ് മോഡ്"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"USB ഡീബഗ്ഗിംഗ് അംഗീകാരം പിൻവലിക്കുക"</string>
<string name="bugreport_in_power" msgid="7923901846375587241">"ബഗ് റിപ്പോർട്ട് കുറുക്കുവഴി"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"ബഗ് റിപ്പോർട്ട് എടുക്കുന്നതിന് പവർ മെനുവിൽ ഒരു ബട്ടൺ കാണിക്കുക"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"സജീവമായി തുടരുക"</string>
- <string name="keep_screen_on_summary" msgid="2173114350754293009">"ചാർജ്ജ് ചെയ്യുമ്പോൾ സ്ക്രീൻ ഒരിക്കലും ഉറങ്ങില്ല"</string>
+ <string name="keep_screen_on_summary" msgid="2173114350754293009">"ചാർജ് ചെയ്യുമ്പോൾ സ്ക്രീൻ ഒരിക്കലും സ്ലീപ്പ് മോഡിലാകില്ല"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ബ്ലൂടൂത്ത് HCI സ്നൂപ്പ് ലോഗ് സജീവമാക്കൂ"</string>
<string name="bt_hci_snoop_log_summary" msgid="8857606786588106495">"Bluetooth പായ്ക്കറ്റുകൾ ക്യാപ്ചർ ചെയ്യുക. (ഈ ക്രമീകരണം മാറ്റിയ ശേഷം Bluetooth മാറ്റുക)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM അൺലോക്ക് ചെയ്യൽ"</string>
@@ -215,7 +216,7 @@
<string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"മുന്നറിയിപ്പ്: ഈ ക്രമീകരണം ഓണായിരിക്കുമ്പോൾ, ഉപകരണ സുരക്ഷാ ഫീച്ചറുകൾ ഈ ഉപകരണത്തിൽ പ്രവർത്തിക്കില്ല."</string>
<string name="mock_location_app" msgid="7966220972812881854">"മോക്ക്ലൊക്കേഷൻ ആപ്പ് തിരഞ്ഞെടുക്കൂ"</string>
<string name="mock_location_app_not_set" msgid="809543285495344223">"മോക്ക് ലൊക്കേഷൻ ആപ്പ് സജ്ജമാക്കിയിട്ടില്ല"</string>
- <string name="mock_location_app_set" msgid="8966420655295102685">"വ്യാജ ലൊക്കേഷൻ ആപ്പ്: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app_set" msgid="8966420655295102685">"മോക്ക് ലൊക്കേഷൻ ആപ്പ്: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="7044075693643009662">"നെറ്റ്വര്ക്കിംഗ്"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"വയർലെസ് ഡിസ്പ്ലേ സർട്ടിഫിക്കേഷൻ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"വൈഫൈ വെർബോസ് ലോഗിംഗ് പ്രവർത്തനക്ഷമമാക്കുക"</string>
@@ -319,7 +320,7 @@
<string name="transition_animation_scale_title" msgid="387527540523595875">"സംക്രമണ ആനിമേഷൻ സ്കെയിൽ"</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"ആനിമേറ്റർ ദൈർഘ്യ സ്കെയിൽ"</string>
<string name="overlay_display_devices_title" msgid="5364176287998398539">"രണ്ടാം ഡിസ്പ്ലേകൾ പ്രവർത്തിപ്പിക്കുക"</string>
- <string name="debug_applications_category" msgid="4206913653849771549">"അപ്ലിക്കേഷനുകൾ"</string>
+ <string name="debug_applications_category" msgid="4206913653849771549">"ആപ്പുകൾ"</string>
<string name="immediately_destroy_activities" msgid="1579659389568133959">"പ്രവർത്തനങ്ങൾ സൂക്ഷിക്കരുത്"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"ഉപയോക്താവ് ഉപേക്ഷിക്കുന്നതിനനുസരിച്ച് എല്ലാ പ്രവർത്തനങ്ങളും നശിപ്പിക്കുക"</string>
<string name="app_process_limit_title" msgid="4280600650253107163">"പശ്ചാത്തല പ്രോസസ് പരിധി"</string>
@@ -450,7 +451,7 @@
<string name="okay" msgid="1997666393121016642">"ശരി"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ഓണാക്കുക"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\'ശല്യപ്പെടുത്തരുത്\' ഓണാക്കുക"</string>
- <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"ഒരിക്കലും ഇല്ല"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"ഒരിക്കലും വേണ്ട"</string>
<string name="zen_interruption_level_priority" msgid="2078370238113347720">"മുൻഗണന മാത്രം"</string>
<string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
<string name="zen_alarm_warning_indef" msgid="3007988140196673193">"ഇത് ഓഫാക്കിയില്ലെങ്കിൽ <xliff:g id="WHEN">%1$s</xliff:g>-നുള്ള അടുത്ത അലാറം കേൾക്കില്ല"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 78d9ed7..46029c7 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Сүлжээнүүдийг скан хийх боломжгүй"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Байхгүй"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Хадгалагдсан"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Салсан"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Идэвхгүйжүүлсэн"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP тохируулга амжилтгүй"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Сүлжээний чанар муу байгаа тул холбогдож чадсангүй"</string>
@@ -220,7 +221,7 @@
<string name="wifi_display_certification" msgid="8611569543791307533">"Утасгүй дэлгэцийн сертификат"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi дэлгэрэнгүй лог-г идэвхжүүлэх"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобайл дата байнга идэвхтэй"</string>
- <string name="tethering_hardware_offload" msgid="7470077827090325814">"Модем болгох хардвер хурдасгуур"</string>
+ <string name="tethering_hardware_offload" msgid="7470077827090325814">"Модем болгох техник хангамжийн хурдасгуур"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Нэргүй Bluetooth төхөөрөмжийг харуулах"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Үнэмлэхүй дууны түвшинг идэвхгүй болгох"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP хувилбар"</string>
@@ -259,7 +260,7 @@
<string name="allow_mock_location_summary" msgid="317615105156345626">"Хуурамч байршлыг зөвшөөрөх"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"Харах тохируулгын шалгалтыг идэвхжүүлэх"</string>
<string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Wi‑Fi идэвхтэй байхад ч гэсэн гар утасны датаг идэвхтэй байлгадаг (сүлжээг түргэн солихын тулд)."</string>
- <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Модем болгох хардвер хурдасгуурыг боломжтой тохиолдолд ашиглах"</string>
+ <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Модем болгох техник хангамжийн хурдасгуурыг боломжтой тохиолдолд ашиглах"</string>
<string name="adb_warning_title" msgid="6234463310896563253">"USB дебаг хийхийг зөвшөөрөх үү?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"USB дебаг нь зөвхөн хөгжүүлэлтийн зорилготой. Үүнийг өөрийн компьютер болон төхөөрөмжийн хооронд өгөгдөл хуулах, өөрийн төхөөрөмж дээр мэдэгдэлгүйгээр аппликейшн суулгах, лог датаг унших зэрэгт ашиглаж болно."</string>
<string name="adb_keys_warning_message" msgid="5659849457135841625">"Таны өмнө нь зөвшөөрөл өгсөн бүх компьютерээс USB дебаг хандалтыг нь хураах уу?"</string>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index d8652bf..a364db9 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -258,7 +258,7 @@
<item msgid="5220695614993094977">"MTP (मीडिया स्थानांतरण प्रोटोकॉल)"</item>
<item msgid="2086000968159047375">"PTP (चित्र स्थानांतरण प्रोटोकॉल)"</item>
<item msgid="7398830860950841822">"RNDIS (USB इथरनेट)"</item>
- <item msgid="1718924214939774352">"ऑडिओ स्त्रोत"</item>
+ <item msgid="1718924214939774352">"ऑडिओ स्रोत"</item>
<item msgid="8126315616613006284">"MIDI"</item>
</string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 854f5ba..5f6acf1 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"नेटवर्कसाठी स्कॅन करू शकत नाही"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"काहीही नाही"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"सेव्ह केले"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"डिस्कनेक्ट केले"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"अक्षम"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP कॉन्फिगरेशन अयशस्वी"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"कमी दर्जाच्या नेटवर्कमुळे कनेक्ट केलेले नाही"</string>
@@ -87,7 +88,7 @@
<string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"संपर्क सामायिकरणासाठी वापरा"</string>
<string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"इंटरनेट कनेक्शन शेअररण"</string>
<string name="bluetooth_profile_map" msgid="1019763341565580450">"मजकूर मेसेज"</string>
- <string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम प्रवेश"</string>
+ <string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम अॅक्सेस"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ऑडिओ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ऑडिओ"</string>
<string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"श्रवण यंत्रे"</string>
@@ -175,7 +176,7 @@
<string name="tts_status_checking" msgid="5339150797940483592">"तपासत आहे..."</string>
<string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> साठी सेटिंग्ज"</string>
<string name="tts_engine_settings_button" msgid="1030512042040722285">"इंजिन सेटिंग्ज लाँच करा"</string>
- <string name="tts_engine_preference_section_title" msgid="448294500990971413">"प्राधान्यकृत इंजिन"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"प्राधान्य इंजिन"</string>
<string name="tts_general_section_title" msgid="4402572014604490502">"सामान्य"</string>
<string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"उच्चार पिच रीसेट करा"</string>
<string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"डीफॉल्टवर मजकूर ज्या पिचवर बोलला जातो तो रीसेट करा."</string>
@@ -203,8 +204,8 @@
<string name="enable_adb" msgid="7982306934419797485">"USB डीबग करणे"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"USB कनेक्ट केलेले असताना डीबग मोड"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"USB डीबग करणारी प्रमाणीकरणे रीव्होक करा"</string>
- <string name="bugreport_in_power" msgid="7923901846375587241">"बग रीपोर्ट शॉर्टकट"</string>
- <string name="bugreport_in_power_summary" msgid="1778455732762984579">"बग रीपोर्ट घेण्यासाठी पॉवर मेनूमध्ये एक बटण दर्शवा"</string>
+ <string name="bugreport_in_power" msgid="7923901846375587241">"बग रिपोर्ट शॉर्टकट"</string>
+ <string name="bugreport_in_power_summary" msgid="1778455732762984579">"बग रिपोर्ट घेण्यासाठी पॉवर मेनूमध्ये एक बटण दर्शवा"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"सक्रिय रहा"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"चार्ज होत असताना स्क्रीन कधीही निष्क्रिय होणार नाही"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ब्लूटूथ HCI स्नूप लॉग सुरू करा"</string>
@@ -240,7 +241,7 @@
<string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"खाजगी DNS मोड निवडा"</string>
<string name="private_dns_mode_off" msgid="8236575187318721684">"बंद"</string>
<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" msgid="8354935160639360804">"खाजगी DNS पुरवठादार होस्टनाव"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS पुरवठादाराचे होस्टनाव टाका"</string>
<string name="private_dns_mode_provider_failure" msgid="231837290365031223">"कनेक्ट करू शकलो नाही"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस डिस्प्ले प्रमाणिकरणाचे पर्याय दाखवा"</string>
@@ -290,13 +291,13 @@
<string name="strict_mode_summary" msgid="142834318897332338">"मुख्य थ्रेडवर अॅप्स मोठी कार्ये करतात तेव्हा स्क्रीन फ्लॅश करा"</string>
<string name="pointer_location" msgid="6084434787496938001">"पॉइंटर स्थान"</string>
<string name="pointer_location_summary" msgid="840819275172753713">"वर्तमान स्पर्श डेटा दर्शविणारे स्क्रीन ओव्हरले"</string>
- <string name="show_touches" msgid="2642976305235070316">"टॅप दर्शवा"</string>
+ <string name="show_touches" msgid="2642976305235070316">"टॅप दाखवा"</string>
<string name="show_touches_summary" msgid="6101183132903926324">"टॅपसाठी दृश्यमान अभिप्राय दर्शवा"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"पृष्ठभाग अपडेट दर्शवा"</string>
<string name="show_screen_updates_summary" msgid="2569622766672785529">"संपूर्ण विंडो पृष्ठभाग अद्ययावत होतात तेव्हा ते फ्लॅश करा"</string>
<string name="show_hw_screen_updates" msgid="4117270979975470789">"व्ह्यू अपडेट दाखवा"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"रेखांकित केल्यावर विंडोच्या आतील फ्लॅश व्ह्यू"</string>
- <string name="show_hw_layers_updates" msgid="5645728765605699821">"हार्डवेअर स्तर अपडेट दर्शवा"</string>
+ <string name="show_hw_layers_updates" msgid="5645728765605699821">"हार्डवेअर स्तर अपडेट दाखवा"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"हार्डवेअर स्तर अद्ययावत झाल्यावर ते हिरव्या रंगात फ्लॅश करा"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ओव्हरड्रॉ डीबग करा"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW ओव्हरले बंद करा"</string>
@@ -305,7 +306,7 @@
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"OpenGL ट्रेस सुरू करा"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"USB ऑडिओ राउटिंग बंद करा"</string>
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"USB ऑडिओ परिधीय वरील स्वयंचलित राउटिंग बंद करा"</string>
- <string name="debug_layout" msgid="5981361776594526155">"लेआउट सीमा दर्शवा"</string>
+ <string name="debug_layout" msgid="5981361776594526155">"लेआउट सीमा दाखवा"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"क्लिप सीमा, समास इत्यादी दर्शवा."</string>
<string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL लेआउट दिशानिर्देशाची सक्ती करा"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"सर्व लोकॅलसाठी RTL स्क्रीन लेआउट दिशानिर्देशाची सक्ती करा"</string>
@@ -332,7 +333,7 @@
<string name="force_resizable_activities" msgid="8615764378147824985">"अॅक्टिव्हिटीचा आकार बदलण्यायोग्य होण्याची सक्ती करा"</string>
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"manifest मूल्यांकडे दुर्लक्ष करून, एकाहून अधिक-विंडोसाठी सर्व अॅक्टिव्हिटींचा आकार बदलण्यायोग्य करा."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"freeform विंडो सुरू करा"</string>
- <string name="enable_freeform_support_summary" msgid="8247310463288834487">"प्रायोगिक मुक्तस्वरूपाच्या विंडोसाठी समर्थन सुरू करा."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"प्रायोगिक मुक्तस्वरूपाच्या विंडोसाठी सपोर्ट सुरू करा."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"डेस्कटॉप बॅकअप पासवर्ड"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"डेस्कटॉप पूर्ण बॅक अप सध्या संरक्षित नाहीत"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"डेस्कटॉपच्या पूर्ण बॅकअपसाठी असलेला पासवर्ड बदलण्यासाठी किंवा काढण्यासाठी टॅप करा"</string>
@@ -354,8 +355,8 @@
<string name="inactive_app_inactive_summary" msgid="5091363706699855725">"निष्क्रिय. टॉगल करण्यासाठी टॅप करा."</string>
<string name="inactive_app_active_summary" msgid="4174921824958516106">"सक्रिय. टॉगल करण्यासाठी टॅप करा."</string>
<string name="standby_bucket_summary" msgid="6567835350910684727">"अॅप स्टँडबाय स्थिती: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="runningservices_settings_title" msgid="8097287939865165213">"चालू सेवा"</string>
- <string name="runningservices_settings_summary" msgid="854608995821032748">"सध्या चालत असलेल्या सेवा पहा आणि नियंत्रित करा"</string>
+ <string name="runningservices_settings_title" msgid="8097287939865165213">"सुरू सेवा"</string>
+ <string name="runningservices_settings_summary" msgid="854608995821032748">"सध्या सुरू असलेल्या सेवा पहा आणि नियंत्रित करा"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"वेबदृश्य अंमलबजावणी"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"वेबदृश्य अंमलबजावणी सेट करा"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"ही निवड यापुढे वैध असणार नाही. पुन्हा प्रयत्न करा."</string>
@@ -438,11 +439,11 @@
<string name="ims_reg_title" msgid="7609782759207241443">"IMS नोंदणी स्थिती"</string>
<string name="ims_reg_status_registered" msgid="933003316932739188">"नोंदवलेले"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"नोंदवलेले नाही"</string>
- <string name="status_unavailable" msgid="7862009036663793314">"अनुपलब्ध"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"उपलब्ध नाही"</string>
<string name="wifi_status_mac_randomized" msgid="5589328382467438245">"MAC रँडमाइझ केला आहे"</string>
<plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
- <item quantity="one">%1$d डिव्हाइस कनेक्ट केले आहे</item>
<item quantity="other">%1$d डिव्हाइस कनेक्ट केली आहेत</item>
+ <item quantity="one">%1$d डिव्हाइस कनेक्ट केले आहे</item>
</plurals>
<string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"जास्त वेळ."</string>
<string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"कमी वेळ."</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 5a77a22..03ff0bb 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tidak boleh mengimbas untuk rangkaian"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Tiada"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Disimpan"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Diputuskan sambungan"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Dinyahdayakan"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Kegagalan Konfigurasi IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Tidak disambungkan kerana rangkaian berkualiti rendah"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index ee64ea4..4500209 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ကွန်ယက်များကို စကင်မလုပ်နိုင်ပါ"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"တစ်ခုမျှ မဟုတ်ပါ"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"သိမ်းဆည်းပြီး"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"ချိတ်ဆက်မထားပါ"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ပိတ်ထားသည်"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ပြုပြင်ခြင်း မအောင်မြင်ပါ"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ကွန်ရက်ချိတ်ဆက်မှု အားနည်းသည့်အတွက် ချိတ်ဆက်ထားခြင်း မရှိပါ"</string>
@@ -193,7 +194,7 @@
<string name="choose_profile" msgid="6921016979430278661">"ပရိုဖိုင်ကို ရွေးရန်"</string>
<string name="category_personal" msgid="1299663247844969448">"ကိုယ်ရေး"</string>
<string name="category_work" msgid="8699184680584175622">"အလုပ်"</string>
- <string name="development_settings_title" msgid="215179176067683667">"ဆော့ဝဲလ်ရေးသူ၏ ရွေးချယ်မှုများ"</string>
+ <string name="development_settings_title" msgid="215179176067683667">"ဆော့ဝဲလ်ရေးသူ ရွေးစရာများ"</string>
<string name="development_settings_enable" msgid="542530994778109538">"တီထွင်သူများ ရွေးစရာကို ဖွင့်ပါ"</string>
<string name="development_settings_summary" msgid="1815795401632854041">"အပလီကေးရှင်းတိုးတက်မှုအတွက် ရွေးချယ်မှုကိုသတ်မှတ်သည်"</string>
<string name="development_settings_not_available" msgid="4308569041701535607">"ဤသုံးစွဲသူအတွက် တည်ဆောက်သူ ရွေးချယ်ခွင့်များ မရနိုင်ပါ"</string>
@@ -201,7 +202,7 @@
<string name="tethering_settings_not_available" msgid="6765770438438291012">"ဤ အသုံးပြုသူ အတွက် ချိတ်တွဲရေး ဆက်တင်များကို မရယူနိုင်"</string>
<string name="apn_settings_not_available" msgid="7873729032165324000">"ဤ အသုံးပြုသူ အတွက် ဝင်လိုသည့် နေရာ အမည်၏ ဆက်တင်များကို မရယူနိုင်"</string>
<string name="enable_adb" msgid="7982306934419797485">"USB အမှားရှာခြင်း"</string>
- <string name="enable_adb_summary" msgid="4881186971746056635">"USBနှင့်ဆက်သွယ်ထားလျှင် အမှားရှာဖွေဖယ်ရှားမှုစနစ်စတင်ရန်"</string>
+ <string name="enable_adb_summary" msgid="4881186971746056635">"USB နှင့်ချိတ်ထားလျှင် အမှားရှာဖွေဖယ်ရှားမှုစနစ် စတင်ရန်"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"USB အမှားရှာပြင်ဆင်ခွင့်များ ပြန်ရုပ်သိမ်းခြင်း"</string>
<string name="bugreport_in_power" msgid="7923901846375587241">"ချွတ်ယွင်းမှု အစီရင်ခံရန် ဖြတ်လမ်း"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"ချွတ်ယွင်းမှု အစီရင်ခံစာကို တင်ရန် ပါဝါမီနူးမှ ခလုတ်ကို ပြပါ"</string>
@@ -274,8 +275,8 @@
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP စစ်ဆေးမှု"</string>
<string name="hdcp_checking_dialog_title" msgid="5141305530923283">"HDCP စစ်ဆေးပုံကို သတ်မှတ်မည်"</string>
<string name="debug_debugging_category" msgid="6781250159513471316">"အမှားရှာဖွေဖယ်ရှားခြင်း"</string>
- <string name="debug_app" msgid="8349591734751384446">"အမှားရှာသည့်အပလီကေးရှင်းရွေးချယ်ရန်"</string>
- <string name="debug_app_not_set" msgid="718752499586403499">"အမှားရှာသည့် အပလီကေးရှင်းတစ်ခုမျှ သတ်မှတ်မထားပါ"</string>
+ <string name="debug_app" msgid="8349591734751384446">"အမှားရှာသည့်အက်ပ် ရွေးချယ်ရန်"</string>
+ <string name="debug_app_not_set" msgid="718752499586403499">"အမှားရှာသည့် အပလီကေးရှင်း သတ်မှတ်မထားပါ"</string>
<string name="debug_app_set" msgid="2063077997870280017">"အမှားရှာသည့်အပလီကေးရှင်း: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"အပလီကေးရှင်းရွေးချယ်ရန်"</string>
<string name="no_application" msgid="2813387563129153880">"တခုမှမရှိ"</string>
@@ -332,7 +333,7 @@
<string name="force_resizable_activities" msgid="8615764378147824985">"လုပ်ဆောင်ချက်များ အရွယ်ပြောင်းနိုင်ခြင်း"</string>
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"သတ်မှတ်တန်ဖိုး မည်သို့ပင်ရှိစေ ဝင်းဒိုးများ၏ လုပ်ဆောင်မှုအားလုံးကို အရွယ်အစားပြင်သည်။"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"အခမဲ့ပုံစံ ဝင်းဒိုးကို ဖွင့်ပါ"</string>
- <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ပုံစံမျိုးစုံဝင်းဒိုးများစမ်းသပ်မှုအတွက် အထောက်အပံ့ကိုဖွင့်ပါ"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ပုံစံမျိုးစုံဝင်းဒိုးများ စမ်းသပ်မှုအတွက် အထောက်အပံ့ကို ဖွင့်ပါ"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ဒက်စ်တော့ အရန်စကားဝှက်"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"အလုပ်ခုံတွင် အရန်သိမ်းဆည်းခြင်းများကို လောလောဆယ် မကာကွယ်နိုင်ပါ။"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"စားပွဲတင်ကွန်ပျူတာကို အပြည့်အဝအရံကူးထားရန်အတွက် စကားဝှက်ကို ပြောင်းရန် သို့မဟုတ် ဖယ်ရှားရန် တို့ပါ။"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 094a5da..abb3410 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan ikke søke etter nettverk"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Lagret"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Frakoblet"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Slått av"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurasjonsfeil"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ikke tilkoblet på grunn av nettverk av lav kvalitet"</string>
@@ -218,7 +219,7 @@
<string name="mock_location_app_set" msgid="8966420655295102685">"App for fiktiv plassering: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="7044075693643009662">"Nettverk"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Trådløs skjermsertifisering"</string>
- <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktiver detaljert Wi-Fi-loggføring"</string>
+ <string name="wifi_verbose_logging" msgid="4203729756047242344">"Slå på detaljert Wi-Fi-loggføring"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er alltid aktiv"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvareakselerasjon for internettdeling"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Vis Bluetooth-enheter uten navn"</string>
@@ -266,7 +267,7 @@
<string name="dev_settings_warning_title" msgid="7244607768088540165">"Vil du aktivere utviklingsinnstillingene?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"Disse innstillingene er bare beregnet for bruk under programutvikling. De kan forårsake problemer med enheten din og tilhørende apper."</string>
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Bekreft apper via USB"</string>
- <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Sjekk apper som er installert via ADB/ADT for skadelig adferd."</string>
+ <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Sjekk apper som er installert via ADB/ADT, for skadelig atferd."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth-enheter uten navn (bare MAC-adresser) vises"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Slår av funksjonen for absolutt volum via Bluetooth i tilfelle det oppstår volumrelaterte problemer med eksterne enheter, for eksempel uakseptabelt høyt volum eller mangel på kontroll."</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 094f5ed..7d71fdc 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"सञ्जालका लागि स्क्यान गर्न सक्दैन"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"कुनै पनि होइन"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"सुरक्षित गरियो"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"विच्छेद गरियो"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"असक्षम पारियो"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP विन्यास असफल"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"कम गुणस्तरको नेटवर्कका कारण जडान गर्न सकिएन"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 1d6ffeb..d8154ac 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan niet zoeken naar netwerken"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Geen"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Opgeslagen"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Verbinding verbroken"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Uitgeschakeld"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-configuratie mislukt"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Niet verbonden wegens netwerk van lage kwaliteit"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 20110e9..0ca4e3e 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ନେଟ୍ୱର୍କଗୁଡ଼ିକୁ ଖୋଜିପାରୁନାହିଁ"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"କିଛି ନାହିଁ"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ସେଭ୍ ହୋଇଗଲା"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"ବିଛିନ୍ନ କରାଯାଇଛି"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ଅକ୍ଷମ ହୋଇଛି"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP କନଫିଗରେଶନ ବିଫଳ ହୋଇଛି"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ନିମ୍ନ ମାନର ନେଟ୍ୱର୍କ କାରଣରୁ ସଂଯୁକ୍ତ ହୋଇନାହିଁ"</string>
@@ -153,7 +154,7 @@
<string name="launch_defaults_none" msgid="4241129108140034876">"କୌଣସି ପୂର୍ବ-ନିର୍ଦ୍ଧାରଣ ସେଟ୍ ହୋଇନାହିଁ"</string>
<string name="tts_settings" msgid="8186971894801348327">"ଲେଖା-ରୁ-କଥା ସେଟିଙ୍ଗ୍"</string>
<string name="tts_settings_title" msgid="1237820681016639683">"ଲେଖା-ରୁ-କଥା ଆଉଟପୁଟ୍"</string>
- <string name="tts_default_rate_title" msgid="6030550998379310088">"ସ୍ପୀଚ୍ ଦର"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"ସ୍ପୀଚ୍ ବେଗ"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ଲେଖା ପଢ଼ିବାର ବେଗ"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"ପିଚ୍"</string>
<string name="tts_default_pitch_summary" msgid="1944885882882650009">"ସଂଶ୍ଳେଷିତ ସ୍ପିଚ୍ର ଟୋନ୍ରେ ପ୍ରଭାବ ପକାଏ"</string>
@@ -203,8 +204,8 @@
<string name="enable_adb" msgid="7982306934419797485">"USB ଡିବଗ୍ ହେଉଛି"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"USB ସଂଯୁକ୍ତ ହେବାବେଳେ ଡିବଗ୍ ମୋଡ୍"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"USB ଡିବଗିଙ୍ଗ ଅଧିକାରକୁ କାଢ଼ିଦିଅନ୍ତୁ"</string>
- <string name="bugreport_in_power" msgid="7923901846375587241">"ତ୍ରୁଟି ରିପୋର୍ଟ ଶର୍ଟକଟ୍"</string>
- <string name="bugreport_in_power_summary" msgid="1778455732762984579">"ତ୍ରୁଟି ରିପୋର୍ଟ ଦେବାପାଇଁ ପାୱର୍ ମେନୁରେ ଏକ ବଟନ୍ ଦେଖନ୍ତୁ"</string>
+ <string name="bugreport_in_power" msgid="7923901846375587241">"ବଗ୍ ରିପୋର୍ଟ ସର୍ଟକଟ୍"</string>
+ <string name="bugreport_in_power_summary" msgid="1778455732762984579">"ବଗ୍ ରିପୋର୍ଟ ଦେବାପାଇଁ ପାୱାର୍ ମେନୁରେ ଏକ ବଟନ୍ ଦେଖନ୍ତୁ"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"ଜାଗ୍ରତ ରଖନ୍ତୁ"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"ଚାର୍ଜ ହେବାବେଳେ ସ୍କ୍ରୀନ୍ ଆଦୌ ବନ୍ଦ ହେବନାହିଁ"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ବ୍ଲୁଟୂଥ୍ HCI ସ୍ନୁପ୍ ଲଗ୍ ସକ୍ଷମ କରନ୍ତୁ"</string>
@@ -215,12 +216,12 @@
<string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"ଚେତାବନୀ: ଏହି ସେଟିଙ୍ଗ ଚାଲୁ ଥିବାବେଳେ ଡିଭାଇସ୍ର ସୁରକ୍ଷା ବୈଶିଷ୍ଟ୍ୟ କାମ କରିବ ନାହିଁ"</string>
<string name="mock_location_app" msgid="7966220972812881854">"ମକ୍ ଲୋକେସନ୍ ଆପ୍ର ଚୟନ କରନ୍ତୁ"</string>
<string name="mock_location_app_not_set" msgid="809543285495344223">"କୌଣସି ନକଲି ଲୋକେଶନ ଆପ୍ ସେଟ୍ କରାଯାଇନାହିଁ"</string>
- <string name="mock_location_app_set" msgid="8966420655295102685">"ନକଲି ଲୋକେସନ୍ ଆପ୍: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app_set" msgid="8966420655295102685">"ମକ୍ ଲୋକେସନ୍ ଆପ୍: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="7044075693643009662">"ନେଟ୍ୱର୍କିଙ୍ଗ"</string>
- <string name="wifi_display_certification" msgid="8611569543791307533">"ୱାୟରଲେସ୍ ଡିସ୍ପ୍ଲେ ସର୍ଟିଫିକେଶନ୍"</string>
+ <string name="wifi_display_certification" msgid="8611569543791307533">"ୱାୟରଲେସ୍ ଡିସ୍ପ୍ଲେ ସାର୍ଟିଫିକେସନ୍"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"ୱାଇ-ଫାଇ ଭର୍ବୋସ୍ ଲଗିଙ୍ଗ ସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"ମୋବାଇଲ୍ ଡାଟା ସର୍ବଦା ସକ୍ରିୟ"</string>
- <string name="tethering_hardware_offload" msgid="7470077827090325814">"ଟିଥରିଙ୍ଗ ହାର୍ଡୱେର ବେଗ"</string>
+ <string name="tethering_hardware_offload" msgid="7470077827090325814">"ଟିଥରିଙ୍ଗ ହାର୍ଡୱେର ଆକ୍ସିଲିରେସନ୍"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"ବ୍ଲୁଟୂଥ୍ ଡିଭାଇସ୍ଗୁଡ଼ିକୁ ନାମ ବିନା ଦେଖନ୍ତୁ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ପୂର୍ଣ୍ଣ ଭଲ୍ୟୁମ୍ ଅକ୍ଷମ କରନ୍ତୁ"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ବ୍ଲୁଟୂଥ୍ AVRCP ଭର୍ସନ୍"</string>
@@ -243,7 +244,7 @@
<string name="private_dns_mode_provider" msgid="8354935160639360804">"ବ୍ୟକ୍ତିଗତ DNS ପ୍ରଦାତା ହୋଷ୍ଟନାମ"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ପ୍ରଦାନକାରୀଙ୍କ ହୋଷ୍ଟନାମ ପ୍ରବେଶ କରନ୍ତୁ"</string>
<string name="private_dns_mode_provider_failure" msgid="231837290365031223">"କନେକ୍ଟ କରିହେଲା ନାହିଁ"</string>
- <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ୱେୟାରଲେସ୍ ଡିସ୍ପ୍ଲେ ସର୍ଟିଫିକେଶନ୍ ପାଇଁ ବିକଳ୍ପ ଦେଖାନ୍ତୁ"</string>
+ <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ୱେୟାରଲେସ୍ ଡିସ୍ପ୍ଲେ ସାର୍ଟିଫିକେସନ୍ ପାଇଁ ବିକଳ୍ପ ଦେଖାନ୍ତୁ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ୱାଇ-ଫାଇ ଲଗିଙ୍ଗ ସ୍ତର ବଢ଼ାନ୍ତୁ, ୱାଇ-ଫାଇ ପିକର୍ରେ ପ୍ରତି SSID RSSI ଦେଖାନ୍ତୁ"</string>
<string name="wifi_metered_label" msgid="4514924227256839725">"ମପାଯାଉଥିବା"</string>
<string name="wifi_unmetered_label" msgid="6124098729457992931">"ମପାଯାଉନଥିବା"</string>
@@ -259,14 +260,14 @@
<string name="allow_mock_location_summary" msgid="317615105156345626">"ନକଲି ଲୋକେଶନ୍ର ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"ବିଶେଷତା ଯାଞ୍ଚ ଭ୍ୟୁକୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="mobile_data_always_on_summary" msgid="8149773901431697910">"ୱାଇ-ଫାଇ ସକ୍ରିୟ ଥିଲେ ମଧ୍ୟ ସର୍ବଦା ମୋବାଇଲ୍ ଡାଟାକୁ ସକ୍ରିୟ ରଖନ୍ତୁ (ଦ୍ରୁତ ନେଟ୍ୱର୍କ ସ୍ୱିଚିଙ୍ଗ ପାଇଁ)।"</string>
- <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"ଯଦି ଉପଲବ୍ଧ ଥାଏ, ଟିଥରିଙ୍ଗ ହାର୍ଡୱେର୍ ଆକ୍ସଲରେଶନ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"ଯଦି ଉପଲବ୍ଧ ଥାଏ, ଟିଥରିଙ୍ଗ ହାର୍ଡୱେର୍ ଆକ୍ସିଲିରେସନ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="adb_warning_title" msgid="6234463310896563253">"USB ଡିବଗିଙ୍ଗ କରିବେ?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"USB ଡିବଗିଂ କେବଳ ଡେଭଲପମେଣ୍ଟ ଉଦ୍ଦେଶ୍ୟ ପାଇଁ ଉଦ୍ଦିଷ୍ଟ ଅଟେ। ଆପଣଙ୍କ କମ୍ପ୍ୟୁଟର ଏବଂ ଡିଭାଇସ୍ ମଧ୍ୟରେ ଡାଟା କପି କରିବାକୁ, ବିନା ବିଜ୍ଞପ୍ତିରେ ଆପଣଙ୍କ ଡିଭାଇସରେ ଆପସ୍ ସଂସ୍ଥାପନ କରିବାକୁ, ଏବଂ ଲଗ୍ ଡାଟା ପଢିବାକୁ ଏହା ବ୍ୟବହାର କରନ୍ତୁ।"</string>
<string name="adb_keys_warning_message" msgid="5659849457135841625">"ଅଧିକୃତ ସମସ୍ତ କମ୍ପ୍ୟୁଟରରୁ USB ଡିବଗ୍ କରିବା ଆକ୍ସେସ୍ ପ୍ରତ୍ୟାହାର କରିବେ କି?"</string>
<string name="dev_settings_warning_title" msgid="7244607768088540165">"ଡେଭଲପମେଣ୍ଟ ସେଟିଙ୍ଗ ଅନୁମତି ଦେବେ?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"ଏହି ସେଟିଙ୍ଗଗୁଡ଼ିକ କେବଳ ବିକାଶ ବ୍ୟବହାର ପାଇଁ ଉଦ୍ଦିଷ୍ଟ। ସେଗୁଡ଼ିକ କାରଣରୁ ଆପଣଙ୍କ ଡିଭାଇସ୍ ଓ ଆପ୍ଲିକେଶନ୍ଗୁଡ଼ିକ ଠିକ୍ ଭାବେ କାମ ନକରିପାରେ।"</string>
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB ଜରିଆରେ ଆପ୍ଗୁଡ଼ିକୁ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
- <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT ମାଧ୍ୟମରେ ଇନଷ୍ଟଲ ହୋଇଥିବା ଆପ୍ଗୁଡ଼ିକ ହାନିକାରକ କାର୍ଯ୍ୟକଳାପ କରୁଛି କି ନାହିଁ ଯାଞ୍ଚ କରନ୍ତୁ।"</string>
+ <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT ମାଧ୍ୟମରେ ଇନଷ୍ଟଲ ହୋଇଥିବା ଆପ୍ଗୁଡ଼ିକ କ୍ଷତିକାରକ କି ନୁହେଁ ଯାଞ୍ଚ କରନ୍ତୁ।"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"(କେବଳ MAC ଠିକଣା ଥାଇ) ନାମ ବିନା ବ୍ଲୁଟୂଥ ଡିଭାଇସଗୁଡ଼ିକ ପ୍ରଦର୍ଶିତ ହେବ"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ରିମୋଟ୍ ଡିଭାଇସ୍ଗୁଡ଼ିକରେ ଯଦି ଅସ୍ୱୀକାର୍ଯ୍ୟ ଭାବେ ଉଚ୍ଚ ଭଲ୍ୟୁମ୍ କିମ୍ବା ନିୟନ୍ତ୍ରଣର ଅଭାବ ପରି ଭଲ୍ୟୁମ୍ ସମସ୍ୟା ଥାଏ, ବ୍ଲୁଟୂଥ୍ ପୂର୍ଣ୍ଣ ଭଲ୍ୟୁମ୍ ଫିଚର୍ ଅକ୍ଷମ କରିଥାଏ।"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"ସ୍ଥାନୀୟ ଟର୍ମିନାଲ୍"</string>
@@ -275,14 +276,14 @@
<string name="hdcp_checking_dialog_title" msgid="5141305530923283">"HDCPର ଯାଞ୍ଚ ଗତିବିଧି ସେଟ୍ କରନ୍ତୁ"</string>
<string name="debug_debugging_category" msgid="6781250159513471316">"ଡିବଗ୍ କରୁଛି"</string>
<string name="debug_app" msgid="8349591734751384446">"ଡିବଗ୍ ଆପ୍ ବାଛନ୍ତୁ"</string>
- <string name="debug_app_not_set" msgid="718752499586403499">"କୌଣସି ଡିବଗ୍ ଆପ୍ଲିକେଶନ୍ ସେଟ୍ ହୋଇନାହିଁ"</string>
+ <string name="debug_app_not_set" msgid="718752499586403499">"କୌଣସି ଡିବଗ୍ ଆପ୍ଲିକେସନ୍ ସେଟ୍ ହୋଇନାହିଁ"</string>
<string name="debug_app_set" msgid="2063077997870280017">"ଆପ୍ଲିକେଶନ୍ ଡିବଗ୍ କରୁଛି: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"ଆପ୍ଲିକେଶନ୍ ବାଛନ୍ତୁ"</string>
<string name="no_application" msgid="2813387563129153880">"କିଛି ନୁହେଁ"</string>
<string name="wait_for_debugger" msgid="1202370874528893091">"ଡିବଗର୍ ପାଇଁ ଅପେକ୍ଷା କରନ୍ତୁ"</string>
- <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ଡିବଗ୍ ହୋଇଥିବା ଆପ୍ଲିକେଶନ୍, ନିଷ୍ପାଦନ ପୂର୍ବରୁ ଆଟାଚ୍ କରିବା ପାଇଁ ଡିବଗର୍କୁ ଅପେକ୍ଷା କରେ"</string>
+ <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ଡିବଗ୍ ହୋଇଥିବା ଆପ୍ଲିକେସନ୍, ନିଷ୍ପାଦନ ପୂର୍ବରୁ ଆଟାଚ୍ କରିବା ପାଇଁ ଡିବଗର୍କୁ ଅପେକ୍ଷା କରେ"</string>
<string name="debug_input_category" msgid="1811069939601180246">"ଇନପୁଟ୍"</string>
- <string name="debug_drawing_category" msgid="6755716469267367852">"ଅଙ୍କନ"</string>
+ <string name="debug_drawing_category" msgid="6755716469267367852">"ଡ୍ରଇଂ"</string>
<string name="debug_hw_drawing_category" msgid="6220174216912308658">"ହାର୍ଡୱେର୍ ଆକ୍ସଲରେଟେଡ୍ ରେଣ୍ଡରିଙ୍ଗ"</string>
<string name="media_category" msgid="4388305075496848353">"ମିଡିଆ"</string>
<string name="debug_monitoring_category" msgid="7640508148375798343">"ମନିଟରିଙ୍ଗ"</string>
@@ -295,13 +296,13 @@
<string name="show_screen_updates" msgid="5470814345876056420">"ସର୍ଫେସ୍ ଅପଡେଟ୍ ଦେଖାନ୍ତୁ"</string>
<string name="show_screen_updates_summary" msgid="2569622766672785529">"ସମଗ୍ର ୱିଣ୍ଡୋ ପୃଷ୍ଠ ଅପଡେଟ୍ ହେବା ବେଳେ ସେଗୁଡ଼ିକ ଫ୍ଲାସ୍ କରନ୍ତୁ"</string>
<string name="show_hw_screen_updates" msgid="4117270979975470789">"ଭ୍ୟୁ ଅପଡେଟ୍ଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ"</string>
- <string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"ଅଙ୍କାଯିବାବେଳେ ୱିଣ୍ଡୋସ୍ ଭିତରେ ଫ୍ଲାଶ୍ ଭ୍ୟୁ"</string>
+ <string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"ଡ୍ର କରାଯିବା ବେଳେ ୱିଣ୍ଡୋସ୍ ଭିତରେ ଫ୍ଲାଶ୍ ଭ୍ୟୁ"</string>
<string name="show_hw_layers_updates" msgid="5645728765605699821">"ହାର୍ଡୱେର୍ ଲେୟର୍ର ଅପଡେଟ୍ ଦେଖାନ୍ତୁ"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ହାର୍ଡୱେର୍ ଲେୟାର୍ ଅପଡେଟ୍ ହେବାବେଳେ ସେଗୁଡ଼ିକୁ ସବୁଜ ରଙ୍ଗରେ ଦେଖାନ୍ତୁ"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ଓଭର୍ଡ୍ର\' ଡିବଗ୍ କରନ୍ତୁ"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW ଓଭର୍ଲେ\' ଅକ୍ଷମ କରନ୍ତୁ"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"ସ୍କ୍ରୀନ୍ କମ୍ପୋଜିଟିଙ୍ଗ ପାଇଁ ସର୍ବଦା GPU ବ୍ୟବହାର କରନ୍ତୁ"</string>
- <string name="simulate_color_space" msgid="6745847141353345872">"ରଙ୍ଗ ସ୍ଥାନ ଅନୁକରଣ କରନ୍ତୁ"</string>
+ <string name="simulate_color_space" msgid="6745847141353345872">"ରଙ୍ଗ ସ୍ଥାନ ସିମୁଲେଟ୍ କରନ୍ତୁ"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"OpenGL ଟ୍ରେସ୍ ସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"USB ଅଡିଓ ରାଉଟିଙ୍ଗ ଅକ୍ଷମ କରନ୍ତୁ"</string>
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"USB ଅଡିଓ ଉପକରଣଗୁଡ଼ିକ ପ୍ରତି ସ୍ୱଚାଳିତ ରାଉଟିଙ୍ଗ ଅକ୍ଷମ କରନ୍ତୁ"</string>
@@ -315,19 +316,19 @@
<string name="track_frame_time" msgid="6094365083096851167">"ପ୍ରୋଫାଇଲ୍ HWUI ରେଣ୍ଡର୍ ହେଉଛି"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"GPU ଡିବଗ୍ ଲେୟର୍ ସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"ଡିବଗ୍ ଆପ୍ଗୁଡ଼ିକ ପାଇଁ GPU ଡିବଗ୍ ଲେୟର୍ ଲୋଡ୍ କରିବାର ଅନୁମତି ଦିଅନ୍ତୁ"</string>
- <string name="window_animation_scale_title" msgid="6162587588166114700">"ୱିଣ୍ଡୋ ଆନିମେଶନ୍ ସ୍କେଲ୍"</string>
- <string name="transition_animation_scale_title" msgid="387527540523595875">"ଟ୍ରାଞ୍ଜିଶନ୍ ଆନିମେଶନ୍ ସ୍କେଲ୍"</string>
+ <string name="window_animation_scale_title" msgid="6162587588166114700">"ୱିଣ୍ଡୋ ଆନିମେସନ୍ ସ୍କେଲ୍"</string>
+ <string name="transition_animation_scale_title" msgid="387527540523595875">"ଟ୍ରାଞ୍ଜିସନ୍ ଆନିମେସନ୍ ସ୍କେଲ୍"</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"ଆନିମେଟର୍ ଅବଧି ସ୍କେଲ୍"</string>
- <string name="overlay_display_devices_title" msgid="5364176287998398539">"ମାଧ୍ୟମିକ ଡିସ୍ପ୍ଲେ ସିମୁଲେଟ୍ କରନ୍ତୁ"</string>
+ <string name="overlay_display_devices_title" msgid="5364176287998398539">"ସେକେଣ୍ଡାରୀ ଡିସ୍ପ୍ଲେ ସିମୁଲେଟ୍ କରନ୍ତୁ"</string>
<string name="debug_applications_category" msgid="4206913653849771549">"ଆପ୍ଗୁଡ଼ିକ"</string>
<string name="immediately_destroy_activities" msgid="1579659389568133959">"କାର୍ଯ୍ୟକଳାପଗୁଡ଼ିକୁ ରଖନ୍ତୁ ନାହିଁ"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"ୟୁଜର୍ ଏହାକୁ ଛାଡ଼ିବା କ୍ଷଣି ସମସ୍ତ କାର୍ଯ୍ୟକଳାପ ନଷ୍ଟ କରିଦିଅନ୍ତୁ"</string>
<string name="app_process_limit_title" msgid="4280600650253107163">"ବ୍ୟାକ୍ଗ୍ରାଉଣ୍ଡ ପ୍ରୋସେସ୍ ସୀମା"</string>
<string name="show_all_anrs" msgid="4924885492787069007">"ବ୍ୟାକଗ୍ରାଉଣ୍ଡରେ ଥିବା ANRଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ"</string>
<string name="show_all_anrs_summary" msgid="6636514318275139826">"ବ୍ୟାକ୍ଗ୍ରାଉଣ୍ଡ ଆପ୍ଗୁଡ଼ିକ ପାଇଁ \"ଆପ୍ ଉତ୍ତର ଦେଉନାହିଁ\" ଡାୟଲଗ୍ ଦେଖାନ୍ତୁ"</string>
- <string name="show_notification_channel_warnings" msgid="1399948193466922683">"ବିଜ୍ଞପ୍ତି ଚାନେଲ୍ ଚେତାବନୀ ଦେଖାଦେଉ"</string>
+ <string name="show_notification_channel_warnings" msgid="1399948193466922683">"ବିଜ୍ଞପ୍ତି ଚେନାଲ୍ ଚେତାବନୀ ଦେଖାନ୍ତୁ"</string>
<string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ବୈଧ ଚ୍ୟାନେଲ୍ ବିନା ଗୋଟିଏ ଆପ୍ ଏକ ବିଜ୍ଞପ୍ତି ପୋଷ୍ଟ କରିବାବେଳେ ଅନ୍-ସ୍କ୍ରୀନ୍ ସତର୍କତା ଦେଖାଏ"</string>
- <string name="force_allow_on_external" msgid="3215759785081916381">"ଆପ୍କୁ ଏକ୍ସଟର୍ନଲ୍ ମେମୋରୀରେ ହିଁ ଚଲାନ୍ତୁ"</string>
+ <string name="force_allow_on_external" msgid="3215759785081916381">"ଆପ୍କୁ ଏକ୍ସଟର୍ନଲ୍ ମେମୋରୀରେ ଫୋର୍ସ୍ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"ଯେକୌଣସି ଆପ୍କୁ ଏକ୍ସଟର୍ନଲ୍ ଷ୍ଟୋରେଜ୍ରେ ଲେଖାଯୋଗ୍ୟ କରନ୍ତୁ, ମେନିଫେଷ୍ଟ ମୂଲ୍ୟ ଯାହା ହୋଇଥାଉ ନା କାହିଁକି"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"ୱିଣ୍ଡୋ ହିସାବରେ କାର୍ଯ୍ୟକଳାପର ଆକାର ବଦଳାନ୍ତୁ"</string>
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"ୱିଣ୍ଡୋ ହିସାବରେ କାର୍ଯ୍ୟକଳାପଗୁଡ଼ିକୁ ବଦଳାନ୍ତୁ, ସେଗୁଡ଼ିକର ମାନିଫେଷ୍ଟ ଭାଲ୍ୟୁ ଯାହା ହୋଇଥାଉ ନା କାହିଁକି"</string>
@@ -406,7 +407,7 @@
<string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ଚାର୍ଜ ହେଉଛି"</string>
<string name="battery_info_status_discharging" msgid="310932812698268588">"ଚାର୍ଜ ହେଉନାହିଁ"</string>
<string name="battery_info_status_not_charging" msgid="8523453668342598579">"ପ୍ଲଗ୍ରେ ଲାଗିଛି, ହେଲେ ଏବେ ଚାର୍ଜ କରିପାରିବ ନାହିଁ"</string>
- <string name="battery_info_status_full" msgid="2824614753861462808">"ଚାର୍ଜ ଅଛି"</string>
+ <string name="battery_info_status_full" msgid="2824614753861462808">"ଚାର୍ଜ ସମ୍ପୂର୍ଣ୍ଣ"</string>
<string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ଆଡ୍ମିନ୍ ଦ୍ୱାରା ନିୟନ୍ତ୍ରିତ"</string>
<string name="disabled" msgid="9206776641295849915">"ଅକ୍ଷମ ହୋଇଛି"</string>
<string name="external_source_trusted" msgid="2707996266575928037">"ଅନୁମୋଦିତ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 5f80abd..6fff4d8 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ਨੈਟਵਰਕਾਂ ਲਈ ਸਕੈਨ ਨਹੀਂ ਕਰ ਸਕਦਾ"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"ਕੋਈ ਨਹੀਂ"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ਰੱਖਿਅਤ ਕੀਤਾ"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"ਡਿਸਕਨੈਕਟ ਹੋਇਆ"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ਅਯੋਗ ਬਣਾਇਆ"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ਕੌਂਫਿਗਰੇਸ਼ਨ ਅਸਫਲਤਾ"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ਘੱਟ ਗੁਣਵੱਤਾ ਵਾਲੇ ਨੈੱਟਵਰਕ ਕਾਰਨ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ"</string>
@@ -152,7 +153,7 @@
<string name="launch_defaults_some" msgid="313159469856372621">"ਕੁਝ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈੱਟ ਕੀਤੇ"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"ਕੋਈ ਡਿਫੌਲਟਸ ਸੈਟ ਨਹੀਂ ਕੀਤੇ"</string>
<string name="tts_settings" msgid="8186971894801348327">"ਲਿਖਤ ਤੋਂ ਬੋਲੀ ਸੈਟਿੰਗਾਂ"</string>
- <string name="tts_settings_title" msgid="1237820681016639683">"ਲਿਖਤ-ਤੋਂ-ਬੋਲੀ ਆਊਟਪੁੱਟ"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"ਲਿਖਤ ਤੋਂ ਬੋਲੀ ਆਊਟਪੁੱਟ"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"ਬੋਲਣ ਦੀ ਗਤੀ"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ਸਪੀਡ ਜਿਸਤੇ ਟੈਕਸਟ ਬੋਲਿਆ ਜਾਂਦਾ ਹੈ"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"ਪਿਚ"</string>
@@ -305,10 +306,10 @@
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"OpenGL ਟ੍ਰੇਸਿਜ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"USB ਆਡੀਓ ਰੂਟਿੰਗ ਨੂੰ ਬੰਦ ਕਰੋ"</string>
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"USB ਆਡੀਓ ਪੈਰੀਫੈਰਲ ਲਈ ਸਵੈਚਲਿਤ ਰੂਟਿੰਗ ਬੰਦ ਕਰੋ"</string>
- <string name="debug_layout" msgid="5981361776594526155">"ਲੇਆਉਟ ਬਾਊਂਡਸ ਦਿਖਾਓ"</string>
- <string name="debug_layout_summary" msgid="2001775315258637682">"ਕਲਿਪ ਬਾਊਂਡਸ, ਮਾਰਜਿਨ ਆਦਿ ਦਿਖਾਓ"</string>
+ <string name="debug_layout" msgid="5981361776594526155">"ਖਾਕਾ ਸੀਮਾਵਾਂ ਦਿਖਾਓ"</string>
+ <string name="debug_layout_summary" msgid="2001775315258637682">"ਕਲਿੱਪ ਸੀਮਾਵਾਂ, ਹਾਸ਼ੀਏ ਆਦਿ ਦਿਖਾਓ"</string>
<string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਵਾਲਾ ਲੇਆਊਟ ਲਾਗੂ ਕਰੋ"</string>
- <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"ਸਾਰੇ ਸਥਾਨਾਂ ਲਈ ਸਕ੍ਰੀਨ \'ਤੇ ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਵਾਲਾ ਲੇਆਊਟ ਲਾਗੂ ਕਰੋ"</string>
+ <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ ਲਈ ਸਕ੍ਰੀਨ \'ਤੇ ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਵਾਲਾ ਲੇਆਊਟ ਲਾਗੂ ਕਰੋ"</string>
<string name="force_msaa" msgid="7920323238677284387">"4x MSAA ਤੇ ਜ਼ੋਰ ਪਾਓ"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"OpenGL ES 2.0 ਐਪਾਂ ਵਿੱਚ 4x MSAA ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"ਗੈਰ-ਆਇਤਾਕਾਰ ਕਲਿੱਪ ਓਪਰੇਸ਼ਨ ਡੀਬੱਗ ਕਰੋ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 3d58aa7..bed4d63 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nie można wyszukać sieci."</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Brak"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Zapisana"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Rozłączona"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Wyłączona"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Błąd konfiguracji IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Brak połączenia z powodu słabego sygnału sieci"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 7868649..1348715 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar a existência de redes"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Salva"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Desconectado"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Não conectado devido à baixa qualidade da rede"</string>
@@ -83,8 +84,8 @@
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferência de arquivo"</string>
<string name="bluetooth_profile_hid" msgid="3680729023366986480">"Dispositivo de entrada"</string>
<string name="bluetooth_profile_pan" msgid="3391606497945147673">"Acesso à Internet"</string>
- <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Compartilhamento de contatos"</string>
- <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Usar para compartilhamento de contatos"</string>
+ <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Compartilhar contatos"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Usar para compartilhar contatos"</string>
<string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"Compartilhamento de conexão à Internet"</string>
<string name="bluetooth_profile_map" msgid="1019763341565580450">"Mensagens de texto"</string>
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso ao chip"</string>
@@ -203,7 +204,7 @@
<string name="enable_adb" msgid="7982306934419797485">"Depuração USB"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"Modo de depuração quando o USB estiver conectado"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"Revogar autorizações de depuração USB"</string>
- <string name="bugreport_in_power" msgid="7923901846375587241">"Atalho para relatório do bug"</string>
+ <string name="bugreport_in_power" msgid="7923901846375587241">"Atalho para relatório de bugs"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Permanecer ativo"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"A tela nunca entrará em suspensão enquanto estiver carregando"</string>
@@ -237,7 +238,7 @@
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Acionar seleção de codec de áudio\nBluetooth LDAC: qualidade de reprodução"</string>
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS particular"</string>
- <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo de DNS particular"</string>
+ <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecionar modo DNS particular"</string>
<string name="private_dns_mode_off" msgid="8236575187318721684">"Desativado"</string>
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automático"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome do host do provedor de DNS particular"</string>
@@ -268,7 +269,7 @@
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar apps por USB"</string>
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificar comportamento nocivo em apps instalados via ADB/ADT"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Dispositivos Bluetooth sem nomes (somente endereços MAC) serão exibidos"</string>
- <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle."</string>
+ <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Ativar o app terminal que oferece acesso ao shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Verificação HDCP"</string>
@@ -292,19 +293,19 @@
<string name="pointer_location_summary" msgid="840819275172753713">"Exibir dados de toque"</string>
<string name="show_touches" msgid="2642976305235070316">"Mostrar toques"</string>
<string name="show_touches_summary" msgid="6101183132903926324">"Mostrar feedback visual para toques"</string>
- <string name="show_screen_updates" msgid="5470814345876056420">"Mostrar atual. superfície"</string>
+ <string name="show_screen_updates" msgid="5470814345876056420">"Mostrar superfície atualizada"</string>
<string name="show_screen_updates_summary" msgid="2569622766672785529">"Piscar superfícies de toda a janela ao atualizar"</string>
- <string name="show_hw_screen_updates" msgid="4117270979975470789">"Ver atual. de exibição"</string>
+ <string name="show_hw_screen_updates" msgid="4117270979975470789">"Ver atualizações de exibição"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Piscar visualizações em janelas ao desenhar"</string>
- <string name="show_hw_layers_updates" msgid="5645728765605699821">"Atual. camad. de hardware"</string>
+ <string name="show_hw_layers_updates" msgid="5645728765605699821">"Atualizações de camadas de hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Piscar camadas de hardware em verde ao atualizar"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar overdraw da GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Desativar sobreposição HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Sempre usar a GPU para composição de tela"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simular espaço de cores"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"Ativar rastream. OpenGL"</string>
- <string name="usb_audio_disable_routing" msgid="8114498436003102671">"Desat. roteam. áudio USB"</string>
- <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Desativar roteam. autom. p/ perif. de áudio USB"</string>
+ <string name="usb_audio_disable_routing" msgid="8114498436003102671">"Desativar roteamento de áudio USB"</string>
+ <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Desativar roteamento automático p/ periféricos de áudio USB"</string>
<string name="debug_layout" msgid="5981361776594526155">"Mostrar limites de layout"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"Mostrar limites de corte, margens, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forçar layout da direita p/ esquerda"</string>
@@ -312,7 +313,7 @@
<string name="force_msaa" msgid="7920323238677284387">"Forçar 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Ativar 4x MSAA em apps OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"Depurar operações de corte não retangulares"</string>
- <string name="track_frame_time" msgid="6094365083096851167">"Classific. render. HWUI"</string>
+ <string name="track_frame_time" msgid="6094365083096851167">"Classificar renderização HWUI"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Ativar camadas de depuração de GPU"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Permitir carreg. de camadas de depuração de GPU p/ apps de dep"</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Escala de animação da janela"</string>
@@ -322,19 +323,19 @@
<string name="debug_applications_category" msgid="4206913653849771549">"Apps"</string>
<string name="immediately_destroy_activities" msgid="1579659389568133959">"Não manter atividades"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Destruir todas as atividades quando o usuário sair"</string>
- <string name="app_process_limit_title" msgid="4280600650253107163">"Limite do proc. 2º plano"</string>
+ <string name="app_process_limit_title" msgid="4280600650253107163">"Limite do processamento em 2º plano"</string>
<string name="show_all_anrs" msgid="4924885492787069007">"Mostrar ANRs em 2º plano"</string>
<string name="show_all_anrs_summary" msgid="6636514318275139826">"Exibir a caixa de diálogo \"App não responde\" para apps em segundo plano"</string>
- <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostrar avisos do canal de notif."</string>
+ <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostrar avisos de notificações"</string>
<string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Exibir aviso na tela quando um app posta notificação sem canal válido"</string>
<string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"Qualificar apps para gravação em armazenamento externo, independentemente de valores de manifestos"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string>
- <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ativar a compatibilidade com janelas de forma livre experimentais."</string>
- <string name="local_backup_password_title" msgid="3860471654439418822">"Senha do backup local"</string>
- <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Os backups completos do computador não estão protegidos no momento"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ativar a compatibilidade com janelas experimentais de forma livre."</string>
+ <string name="local_backup_password_title" msgid="3860471654439418822">"Senha de backup local"</string>
+ <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Os backups completos não estão protegidos no momento"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toque para alterar ou remover a senha de backups completos do desktop"</string>
<string name="local_backup_password_toast_success" msgid="582016086228434290">"Nova senha de backup definida"</string>
<string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"A nova senha e a confirmação não coincidem."</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 34f8e7d..3b0b86c 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar redes"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Guardada"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Desligada"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Não ligado devido à baixa qualidade da rede"</string>
@@ -292,48 +293,48 @@
<string name="pointer_location_summary" msgid="840819275172753713">"Apresentar dados atuais de toque"</string>
<string name="show_touches" msgid="2642976305235070316">"Mostrar toques"</string>
<string name="show_touches_summary" msgid="6101183132903926324">"Mostrar feedback visual para toques"</string>
- <string name="show_screen_updates" msgid="5470814345876056420">"Atualiz. de superfície"</string>
+ <string name="show_screen_updates" msgid="5470814345876056420">"Mostrar superfície atualizada"</string>
<string name="show_screen_updates_summary" msgid="2569622766672785529">"Destacar a superfície da janela ao atualizar"</string>
<string name="show_hw_screen_updates" msgid="4117270979975470789">"Ver atualizações de vistas"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Destacar vistas em janelas quando desenhadas"</string>
- <string name="show_hw_layers_updates" msgid="5645728765605699821">"Mostrar atual. cam. hard."</string>
+ <string name="show_hw_layers_updates" msgid="5645728765605699821">"Atualizações de camadas de hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Camadas de hard. flash verdes quando estão atuali."</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar sobreposição GPU"</string>
- <string name="disable_overlays" msgid="2074488440505934665">"Desativ. sobreposições HW"</string>
+ <string name="disable_overlays" msgid="2074488440505934665">"Desativar sobreposições HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizar sempre GPU para a composição do ecrã"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simular espaço da cor"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"Ativar vestígios OpenGL"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"Desativar encaminhamento áudio USB"</string>
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Desativar encam. auto. para periféricos áudio USB"</string>
- <string name="debug_layout" msgid="5981361776594526155">"Mostrar limit. do esquema"</string>
+ <string name="debug_layout" msgid="5981361776594526155">"Mostrar limites do esquema"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"Apresentar limites de clipes, margens, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forçar direção do esquema RTL"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Forçar dir. do esq. do ecrã p. RTL tds os locais"</string>
<string name="force_msaa" msgid="7920323238677284387">"Forçar 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Ativar o 4x MSAA em aplicações OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"Depurar operações de clipe não retangulares"</string>
- <string name="track_frame_time" msgid="6094365083096851167">"Renderiz. HWUI do perfil"</string>
+ <string name="track_frame_time" msgid="6094365083096851167">"Renderização HWUI do perfil"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Ativar cam. depuração GPU"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Permitir carreg. cam. depuração GPU p/ dep. app"</string>
- <string name="window_animation_scale_title" msgid="6162587588166114700">"Escala de anim. da janela"</string>
- <string name="transition_animation_scale_title" msgid="387527540523595875">"Escala de anim. de trans."</string>
+ <string name="window_animation_scale_title" msgid="6162587588166114700">"Escala de animação de transição"</string>
+ <string name="transition_animation_scale_title" msgid="387527540523595875">"Escala de animação de transição"</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"Escala de duração de animação"</string>
<string name="overlay_display_devices_title" msgid="5364176287998398539">"Simular apresentações secundárias"</string>
<string name="debug_applications_category" msgid="4206913653849771549">"Aplicações"</string>
<string name="immediately_destroy_activities" msgid="1579659389568133959">"Não manter atividades"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Destruir atividades assim que o utilizador sair"</string>
- <string name="app_process_limit_title" msgid="4280600650253107163">"Limite proc. em 2º plano"</string>
+ <string name="app_process_limit_title" msgid="4280600650253107163">"Limite do processo em 2º plano"</string>
<string name="show_all_anrs" msgid="4924885492787069007">"Mostrar ANRs em 2.º plano"</string>
<string name="show_all_anrs_summary" msgid="6636514318275139826">"Mostrar caixa de diálogo A aplicação não está a responder para aplicações em segundo plano"</string>
<string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostrar avisos do canal de notificações"</string>
<string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Mostra um aviso no ecrã quando uma aplicação publica uma notificação sem o canal ser válido"</string>
- <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar perm. de aplicações no armazenamento ext."</string>
+ <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps no armazenamento externo"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"Torna qualquer aplicação elegível para ser gravada no armazenamento externo, independentemente dos valores do manifesto"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forçar as atividades a serem redimensionáveis"</string>
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ativar a compatibilidade com janelas de forma livre experimentais."</string>
- <string name="local_backup_password_title" msgid="3860471654439418822">"Palavra-passe cópia do comp."</string>
+ <string name="local_backup_password_title" msgid="3860471654439418822">"Palavra-passe cópia do computador"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"As cópias de segurança completas no ambiente de trabalho não estão atualmente protegidas"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tocar para alterar ou remover a palavra-passe para cópias de segurança completas no ambiente de trabalho"</string>
<string name="local_backup_password_toast_success" msgid="582016086228434290">"Nova palavra-passe da cópia de segurança definida"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 7868649..1348715 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar a existência de redes"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Salva"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Desconectado"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Não conectado devido à baixa qualidade da rede"</string>
@@ -83,8 +84,8 @@
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferência de arquivo"</string>
<string name="bluetooth_profile_hid" msgid="3680729023366986480">"Dispositivo de entrada"</string>
<string name="bluetooth_profile_pan" msgid="3391606497945147673">"Acesso à Internet"</string>
- <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Compartilhamento de contatos"</string>
- <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Usar para compartilhamento de contatos"</string>
+ <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Compartilhar contatos"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Usar para compartilhar contatos"</string>
<string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"Compartilhamento de conexão à Internet"</string>
<string name="bluetooth_profile_map" msgid="1019763341565580450">"Mensagens de texto"</string>
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso ao chip"</string>
@@ -203,7 +204,7 @@
<string name="enable_adb" msgid="7982306934419797485">"Depuração USB"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"Modo de depuração quando o USB estiver conectado"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"Revogar autorizações de depuração USB"</string>
- <string name="bugreport_in_power" msgid="7923901846375587241">"Atalho para relatório do bug"</string>
+ <string name="bugreport_in_power" msgid="7923901846375587241">"Atalho para relatório de bugs"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Permanecer ativo"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"A tela nunca entrará em suspensão enquanto estiver carregando"</string>
@@ -237,7 +238,7 @@
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Acionar seleção de codec de áudio\nBluetooth LDAC: qualidade de reprodução"</string>
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS particular"</string>
- <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo de DNS particular"</string>
+ <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecionar modo DNS particular"</string>
<string name="private_dns_mode_off" msgid="8236575187318721684">"Desativado"</string>
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automático"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome do host do provedor de DNS particular"</string>
@@ -268,7 +269,7 @@
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar apps por USB"</string>
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificar comportamento nocivo em apps instalados via ADB/ADT"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Dispositivos Bluetooth sem nomes (somente endereços MAC) serão exibidos"</string>
- <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle."</string>
+ <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Ativar o app terminal que oferece acesso ao shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Verificação HDCP"</string>
@@ -292,19 +293,19 @@
<string name="pointer_location_summary" msgid="840819275172753713">"Exibir dados de toque"</string>
<string name="show_touches" msgid="2642976305235070316">"Mostrar toques"</string>
<string name="show_touches_summary" msgid="6101183132903926324">"Mostrar feedback visual para toques"</string>
- <string name="show_screen_updates" msgid="5470814345876056420">"Mostrar atual. superfície"</string>
+ <string name="show_screen_updates" msgid="5470814345876056420">"Mostrar superfície atualizada"</string>
<string name="show_screen_updates_summary" msgid="2569622766672785529">"Piscar superfícies de toda a janela ao atualizar"</string>
- <string name="show_hw_screen_updates" msgid="4117270979975470789">"Ver atual. de exibição"</string>
+ <string name="show_hw_screen_updates" msgid="4117270979975470789">"Ver atualizações de exibição"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Piscar visualizações em janelas ao desenhar"</string>
- <string name="show_hw_layers_updates" msgid="5645728765605699821">"Atual. camad. de hardware"</string>
+ <string name="show_hw_layers_updates" msgid="5645728765605699821">"Atualizações de camadas de hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Piscar camadas de hardware em verde ao atualizar"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar overdraw da GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Desativar sobreposição HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Sempre usar a GPU para composição de tela"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simular espaço de cores"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"Ativar rastream. OpenGL"</string>
- <string name="usb_audio_disable_routing" msgid="8114498436003102671">"Desat. roteam. áudio USB"</string>
- <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Desativar roteam. autom. p/ perif. de áudio USB"</string>
+ <string name="usb_audio_disable_routing" msgid="8114498436003102671">"Desativar roteamento de áudio USB"</string>
+ <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Desativar roteamento automático p/ periféricos de áudio USB"</string>
<string name="debug_layout" msgid="5981361776594526155">"Mostrar limites de layout"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"Mostrar limites de corte, margens, etc."</string>
<string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forçar layout da direita p/ esquerda"</string>
@@ -312,7 +313,7 @@
<string name="force_msaa" msgid="7920323238677284387">"Forçar 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Ativar 4x MSAA em apps OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"Depurar operações de corte não retangulares"</string>
- <string name="track_frame_time" msgid="6094365083096851167">"Classific. render. HWUI"</string>
+ <string name="track_frame_time" msgid="6094365083096851167">"Classificar renderização HWUI"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Ativar camadas de depuração de GPU"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Permitir carreg. de camadas de depuração de GPU p/ apps de dep"</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Escala de animação da janela"</string>
@@ -322,19 +323,19 @@
<string name="debug_applications_category" msgid="4206913653849771549">"Apps"</string>
<string name="immediately_destroy_activities" msgid="1579659389568133959">"Não manter atividades"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Destruir todas as atividades quando o usuário sair"</string>
- <string name="app_process_limit_title" msgid="4280600650253107163">"Limite do proc. 2º plano"</string>
+ <string name="app_process_limit_title" msgid="4280600650253107163">"Limite do processamento em 2º plano"</string>
<string name="show_all_anrs" msgid="4924885492787069007">"Mostrar ANRs em 2º plano"</string>
<string name="show_all_anrs_summary" msgid="6636514318275139826">"Exibir a caixa de diálogo \"App não responde\" para apps em segundo plano"</string>
- <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostrar avisos do canal de notif."</string>
+ <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostrar avisos de notificações"</string>
<string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Exibir aviso na tela quando um app posta notificação sem canal válido"</string>
<string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"Qualificar apps para gravação em armazenamento externo, independentemente de valores de manifestos"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string>
- <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ativar a compatibilidade com janelas de forma livre experimentais."</string>
- <string name="local_backup_password_title" msgid="3860471654439418822">"Senha do backup local"</string>
- <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Os backups completos do computador não estão protegidos no momento"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ativar a compatibilidade com janelas experimentais de forma livre."</string>
+ <string name="local_backup_password_title" msgid="3860471654439418822">"Senha de backup local"</string>
+ <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Os backups completos não estão protegidos no momento"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toque para alterar ou remover a senha de backups completos do desktop"</string>
<string name="local_backup_password_toast_success" msgid="582016086228434290">"Nova senha de backup definida"</string>
<string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"A nova senha e a confirmação não coincidem."</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index ec62c1d..1cbd70bf 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nu se poate scana pentru rețele"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Niciuna"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Salvată"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Deconectat"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Dezactivată"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Eroare de configurație IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nu există conexiune din cauza rețelei de calitate slabă"</string>
@@ -247,8 +248,8 @@
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Măriți niv. de înr. prin Wi‑Fi, afișați în fcț. de SSID RSSI în Selectorul Wi‑Fi"</string>
<string name="wifi_metered_label" msgid="4514924227256839725">"Contorizată"</string>
<string name="wifi_unmetered_label" msgid="6124098729457992931">"Necontorizată"</string>
- <string name="select_logd_size_title" msgid="7433137108348553508">"Dimensiunile tamponului jurnalului"</string>
- <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Dimensiuni jurnal / tampon jurnal"</string>
+ <string name="select_logd_size_title" msgid="7433137108348553508">"Dimensiunile memoriei temporare a jurnalului"</string>
+ <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Dimensiuni jurnal / mem. temp. jurnal"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Ștergeți stocarea permanentă a jurnalului?"</string>
<string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Când nu mai monitorizăm folosind jurnalul permanent, trebuie să ștergem datele de jurnal aflate pe dispozitivul dvs."</string>
<string name="select_logpersist_title" msgid="7530031344550073166">"Stocați date jurnal permanent pe dispozitiv"</string>
@@ -333,8 +334,8 @@
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permiteți redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Activați ferestrele cu formă liberă"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activați compatibilitatea pentru ferestrele experimentale cu formă liberă."</string>
- <string name="local_backup_password_title" msgid="3860471654439418822">"Parolă copie rez. desktop"</string>
- <string name="local_backup_password_summary_none" msgid="6951095485537767956">"În prezent, backupurile complete pe desktop nu sunt protejate"</string>
+ <string name="local_backup_password_title" msgid="3860471654439418822">"Parolă backup computer"</string>
+ <string name="local_backup_password_summary_none" msgid="6951095485537767956">"În prezent, backupurile complete pe computer nu sunt protejate"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Atingeți ca să modificați sau să eliminați parola pentru backupurile complete pe desktop"</string>
<string name="local_backup_password_toast_success" msgid="582016086228434290">"A fost setată o parolă de rezervă nouă"</string>
<string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"Parola nouă și confirmarea acesteia nu se potrivesc."</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 65b2bc5..657e6a9 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не удалось начать поиск сетей."</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Нет"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Сохранено"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Не подключено"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Отключено"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ошибка IP-конфигурации"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Подключение невозможно из-за низкого качества сети"</string>
@@ -225,11 +226,11 @@
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Отключить абсолютный уровень громкости"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версия Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Выберите версию Bluetooth AVRCP"</string>
- <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Аудиокодек для передачи через Bluetooth"</string>
+ <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Аудиокодек Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="8436224899475822557">"Запустить аудиокодек для Bluetooth\nВыбор"</string>
- <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Частота дискретизации при передаче через Bluetooth"</string>
+ <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Частота дискретизации аудио Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Запустить аудиокодек для Bluetooth\nВыбор: частота дискретизации"</string>
- <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Глубина кодирования звука при передаче через Bluetooth"</string>
+ <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Бит на выборку аудио Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="8063859754619484760">"Запустить аудиокодек для Bluetooth\nВыбор: разрядность"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Режим аудиоканала Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="7234956835280563341">"Запустить аудиокодек для Bluetooth\nВыбор: режим канала"</string>
@@ -244,7 +245,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введите имя хоста поставщика услуг DNS"</string>
<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_verbose_logging_summary" msgid="6615071616111731958">"Вести подробный журнал, показывать RSSI для каждого SSID при выборе сети"</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>
@@ -283,15 +284,15 @@
<string name="wait_for_debugger_summary" msgid="1766918303462746804">"Приложение ожидает подключения отладчика"</string>
<string name="debug_input_category" msgid="1811069939601180246">"Ввод"</string>
<string name="debug_drawing_category" msgid="6755716469267367852">"Отрисовка"</string>
- <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Аппаратное ускорение визуализации"</string>
+ <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Аппаратное ускорение отрисовки"</string>
<string name="media_category" msgid="4388305075496848353">"Мультимедиа"</string>
<string name="debug_monitoring_category" msgid="7640508148375798343">"Мониторинг"</string>
<string name="strict_mode" msgid="1938795874357830695">"Строгий режим"</string>
<string name="strict_mode_summary" msgid="142834318897332338">"Подсвечивать экран во время длительных операций"</string>
- <string name="pointer_location" msgid="6084434787496938001">"Место нажатия"</string>
- <string name="pointer_location_summary" msgid="840819275172753713">"Показывать данные нажатий и жестов"</string>
+ <string name="pointer_location" msgid="6084434787496938001">"Место касания"</string>
+ <string name="pointer_location_summary" msgid="840819275172753713">"Показывать данные касаний и жестов"</string>
<string name="show_touches" msgid="2642976305235070316">"Показывать нажатия"</string>
- <string name="show_touches_summary" msgid="6101183132903926324">"Показывать места нажатия на экране"</string>
+ <string name="show_touches_summary" msgid="6101183132903926324">"Визуальный отклик при нажатии"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"Показ. обнов. поверхности"</string>
<string name="show_screen_updates_summary" msgid="2569622766672785529">"Подсвечивать поверхности окон при обновлении"</string>
<string name="show_hw_screen_updates" msgid="4117270979975470789">"Показывать обнов. экрана"</string>
@@ -354,8 +355,8 @@
<string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Выключено. Нажмите, чтобы включить."</string>
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Включено. Нажмите, чтобы отключить."</string>
<string name="standby_bucket_summary" msgid="6567835350910684727">"Статус приложения в режиме ожидания:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="runningservices_settings_title" msgid="8097287939865165213">"Работающие приложения"</string>
- <string name="runningservices_settings_summary" msgid="854608995821032748">"Просмотр и управление работающими приложениями"</string>
+ <string name="runningservices_settings_title" msgid="8097287939865165213">"Работающие службы"</string>
+ <string name="runningservices_settings_summary" msgid="854608995821032748">"Просмотр и управление работающими службами"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Сервис WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Настройки сервиса WebView"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Вариант недействителен. Повторите попытку."</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 4806487..f499253 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ජාල සඳහා පරිලෝකනය කළ නොහැක"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"කිසිවක් නැත"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"සුරකින ලදි"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"විසන්ධි විය"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"අබලයි"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP වින්යාස කිරීම අසාර්ථකයි"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"අඩු ගුණත්වයේ ජාලය හේතුවෙන් සම්බන්ධ නොවීය"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 37221c6..a7895c4 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Siete sa nedajú vyhľadávať"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Žiadne"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Uložené"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Odpojené"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Vypnuté"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Zlyhanie konfigurácie adresy IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nepripojené z dôvodu siete nízkej kvality"</string>
@@ -268,7 +269,7 @@
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Overovať aplikácie z USB"</string>
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrolovať škodlivosť aplikácií nainštalovaných pomocou nástroja ADB alebo ADT"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Zariadenia Bluetooth sa budú zobrazovať bez názvov (iba adresy MAC)"</string>
- <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Umožňuje zakázať funkciu absolútnej hlasitosti rozhrania Bluetooth v prípade problémov s hlasitosťou na vzdialených zariadeniach, ako je napríklad neprijateľne vysoká hlasitosť alebo absencia ovládacích prvkov."</string>
+ <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Umožňuje zakázať funkciu absolútnej hlasitosti rozhrania Bluetooth v prípade problémov s hlasitosťou vo vzdialených zariadeniach, ako je napríklad neprijateľne vysoká hlasitosť alebo absencia ovládacích prvkov."</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Miestny terminál"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Povoliť terminálovú apl. na miestny prístup k prostrediu shell"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Kontrola HDCP"</string>
@@ -307,7 +308,7 @@
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Vypnúť automatické smerovanie do audio periférií USB"</string>
<string name="debug_layout" msgid="5981361776594526155">"Zobrazovať ohraničenia"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"Zobraziť vo výstrižku ohraničenie, okraje a pod."</string>
- <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Rozloženia sprava doľava"</string>
+ <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Rozloženie sprava doľava"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Vynútiť pre všetky jazyky rozloženie obrazovky sprava doľava"</string>
<string name="force_msaa" msgid="7920323238677284387">"Vynútiť 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Povoliť 4x MSAA v aplikáciách OpenGL ES 2.0"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 095d80f..d21e3ad 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ni mogoče iskati omrežij"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Brez"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Shranjeno"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Ni povezave"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogočeno"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Konfiguracija IP-ja ni uspela"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ni povezano zaradi slabe kakovosti omrežja"</string>
@@ -200,10 +201,10 @@
<string name="vpn_settings_not_available" msgid="956841430176985598">"Nastavitve VPN niso na voljo za tega uporabnika"</string>
<string name="tethering_settings_not_available" msgid="6765770438438291012">"Nastavitve za povezavo z internetom prek mobilne naprave niso na voljo za tega uporabnika"</string>
<string name="apn_settings_not_available" msgid="7873729032165324000">"Nastavitve imena dostopne točke niso na voljo za tega uporabnika"</string>
- <string name="enable_adb" msgid="7982306934419797485">"Odpravljanje težav prek USB"</string>
+ <string name="enable_adb" msgid="7982306934419797485">"Odpravljanje težav prek USB-ja"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"Način za odpravljanje težav, ko je vzpostavljena povezava USB"</string>
- <string name="clear_adb_keys" msgid="4038889221503122743">"Preklic dovoljenj za odpr. težav prek USB"</string>
- <string name="bugreport_in_power" msgid="7923901846375587241">"Bližnjica za por. o napakah"</string>
+ <string name="clear_adb_keys" msgid="4038889221503122743">"Preklic dovoljenj za odpravljanje težav prek povezave USB"</string>
+ <string name="bugreport_in_power" msgid="7923901846375587241">"Bližnjica za poročanje o napakah"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Prikaz gumba za ustvarjanje poročila o napakah v meniju za vklop/izklop"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Brez izklopa zaslona"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"Med polnjenjem se zaslon ne bo nikoli izklopil"</string>
@@ -237,7 +238,7 @@
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Sproži kodek LDAC za zvok prek Bluetootha\nIzbira kodeka: kakovost predvajanja"</string>
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Pretočno predvajanje: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Zasebni strežnik DNS"</string>
- <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Izbira načina zasebnega strežnika DNS"</string>
+ <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Izberite način zasebnega strežnika DNS"</string>
<string name="private_dns_mode_off" msgid="8236575187318721684">"Izklopljeno"</string>
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Samodejno"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Ime gostitelja pri ponudniku zasebnega strežnika DNS"</string>
@@ -247,7 +248,7 @@
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povečaj raven zapis. dnev. za Wi-Fi; v izbir. Wi‑Fi-ja pokaži glede na SSID RSSI"</string>
<string name="wifi_metered_label" msgid="4514924227256839725">"Omejen prenos podatkov"</string>
<string name="wifi_unmetered_label" msgid="6124098729457992931">"Z neomejenim prenosom podatkov"</string>
- <string name="select_logd_size_title" msgid="7433137108348553508">"Velikosti medpomn. zapisov. dnevnika"</string>
+ <string name="select_logd_size_title" msgid="7433137108348553508">"Velikosti medpomnilnikov zapisovalnika dnevnika"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izberite velikost medpomnilnika dnevnika"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Želite izbrisati trajno shranjevanje dnevniškega orodja?"</string>
<string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Ko prenehamo spremljanje s trajnim dnevniškim orodjem, moramo podatke tega orodja, shranjene v napravi, izbrisati."</string>
@@ -265,7 +266,7 @@
<string name="adb_keys_warning_message" msgid="5659849457135841625">"Ali želite preklicati dostop do odpravljanja težav prek povezave USB iz vseh računalnikov, ki ste jih pooblastili?"</string>
<string name="dev_settings_warning_title" msgid="7244607768088540165">"Ali želite omogočiti nastavitve za razvijanje?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"Te nastavitve so namenjene samo za razvijanje in lahko povzročijo prekinitev ali napačno delovanje naprave in aplikacij v njej."</string>
- <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Preveri aplikacije prek USB"</string>
+ <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Preveri aplikacije prek USB-ja"</string>
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Preveri, ali so aplikacije, nameščene prek ADB/ADT, škodljive."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Prikazane bodo naprave Bluetooth brez imen (samo z naslovi MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogoči funkcijo absolutne glasnosti za Bluetooth, če pride do težav z glasnostjo z oddaljenimi napravami, kot je nesprejemljivo visoka glasnost ali pomanjkanje nadzora."</string>
@@ -289,7 +290,7 @@
<string name="strict_mode" msgid="1938795874357830695">"Strog način je omogočen"</string>
<string name="strict_mode_summary" msgid="142834318897332338">"Osveži zaslon pri dolgih postopkih v glavni niti"</string>
<string name="pointer_location" msgid="6084434787496938001">"Mesto kazalca"</string>
- <string name="pointer_location_summary" msgid="840819275172753713">"Prekriv. zaslona prikazuje trenutni dotik"</string>
+ <string name="pointer_location_summary" msgid="840819275172753713">"Prekrivanje zaslona prikazuje trenutni dotik"</string>
<string name="show_touches" msgid="2642976305235070316">"Prikaz dotikov"</string>
<string name="show_touches_summary" msgid="6101183132903926324">"Prikaz vizualnih povratnih informacij za dotike"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"Pokaži posodob. površine"</string>
@@ -311,7 +312,7 @@
<string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Vsili smer postavitve na zaslonu od desne proti levi za vse jezike"</string>
<string name="force_msaa" msgid="7920323238677284387">"Vsili 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"V aplikacijah OpenGL ES 2.0 omogoči 4x MSAA"</string>
- <string name="show_non_rect_clip" msgid="505954950474595172">"Odpr. težav s postopki nepravokotnega izrezovanja"</string>
+ <string name="show_non_rect_clip" msgid="505954950474595172">"Odpravljanje težav s postopki nepravokotnega izrezovanja"</string>
<string name="track_frame_time" msgid="6094365083096851167">"Upodob. profilov s HWUI"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Omog. sloje odpr. nap. GPE"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Apl. za odpr. nap. dovoli nal. sloj. odpr. nap. GPE"</string>
@@ -333,7 +334,7 @@
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsem aktivnostim spremeniti velikost za način z več okni."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Omogočanje oken svobodne oblike"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogočanje podpore za poskusna okna svobodne oblike"</string>
- <string name="local_backup_password_title" msgid="3860471654439418822">"Geslo za varn. kop. nam."</string>
+ <string name="local_backup_password_title" msgid="3860471654439418822">"Geslo za varn. kop. namizja"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Popolne varnostne kopije namizja trenutno niso zaščitene"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dotaknite se, če želite spremeniti ali odstraniti geslo za popolno varnostno kopiranje namizja"</string>
<string name="local_backup_password_toast_success" msgid="582016086228434290">"Novo geslo je nastavljeno"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 25e6503..b5f93e4 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nuk mund të skanojë për rrjete"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Asnjë"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"U ruajt"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Shkëputur"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Të çaktivizuara"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Dështim në konfigurimin e IP-së"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nuk është lidhur për shkak të rrjetit me cilësi të dobët"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 6daa22b..2a6e328 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Није могуће скенирати мреже"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Нема"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Сачувано"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Веза је прекинута"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Онемогућено"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурација је отказала"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Није повезано због лошег квалитета мреже"</string>
@@ -152,7 +153,7 @@
<string name="launch_defaults_some" msgid="313159469856372621">"Подешене су неке подразумеване вредности"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Нису подешене подразумеване вредности"</string>
<string name="tts_settings" msgid="8186971894801348327">"Подешавања преласка из текста у говор"</string>
- <string name="tts_settings_title" msgid="1237820681016639683">"Излаз за претварање текста у говор"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Претварање текста у говор"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Брзина говора"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Брзина изговарања текста"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"Ниво"</string>
@@ -207,7 +208,7 @@
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Прикажи дугме у менију напајања за прављење извештаја о грешкама"</string>
<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 евиденцију за Bluetooth HCI"</string>
+ <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Омогући snoop евид. за Bluetooth HCI"</string>
<string name="bt_hci_snoop_log_summary" msgid="8857606786588106495">"Сними Bluetooth пакете. (Укључите/искључите Bluetooth када промените ово подешавање)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"Откључавање OEM-a"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Дозволи откључавање функције за покретање"</string>
@@ -311,8 +312,8 @@
<string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Наметни смер распореда екрана здесна налево за све локалитете"</string>
<string name="force_msaa" msgid="7920323238677284387">"Наметни 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Омогући 4x MSAA у OpenGL ES 2.0 апликацијама"</string>
- <string name="show_non_rect_clip" msgid="505954950474595172">"Отклони грешке исецања области које нису правоугаоног облика"</string>
- <string name="track_frame_time" msgid="6094365083096851167">"Пендеруј помоћу HWUI-а"</string>
+ <string name="show_non_rect_clip" msgid="505954950474595172">"Отклони грешке исецања области неправоугаоног облика"</string>
+ <string name="track_frame_time" msgid="6094365083096851167">"Рендеруј помоћу HWUI-а"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Омогући слојеве за отклањање грешака GPU-a"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Омогући учитавање отк. греш. GPU-a у апл. за отк. греш."</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Размера анимације прозора"</string>
@@ -363,7 +364,7 @@
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертуј..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Већ се користи шифровање датотека"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"Конвертовање у шифровање појединачних датотека"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Конвертујте шифровање партиције података у шифровање појединачних датотека.\n !!Упозорење!! Тиме бришете све податке.\n Ово је алфа верзија функције и вероватно неће функционисати исправно.\n Притисните „Избриши и конвертуј...“ да бисте наставили."</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Конвертујте шифровање партиције података у шифровање појединачних датотека.\n !!Упозорење!! Тиме бришете све податке.\n Ово је алфа верзија функције и вероватно неће радити исправно.\n Притисните „Избриши и конвертуј...“ да бисте наставили."</string>
<string name="button_convert_fbe" msgid="5152671181309826405">"Избриши и конвертуј..."</string>
<string name="picture_color_mode" msgid="4560755008730283695">"Режим боја слика"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"Користи sRGB"</string>
@@ -459,7 +460,7 @@
<string name="alarm_template" msgid="4996153414057676512">"у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Трајање"</string>
- <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Увек питај"</string>
+ <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Питај сваки пут"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Док не искључите"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Управо"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Овај уређај"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 5125909..9778516 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Det går inte att söka efter nätverk"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Sparat"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Frånkopplad"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Inaktiverad"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurationsfel"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ingen anslutning på grund av låg kvalitet på nätverket"</string>
@@ -296,7 +297,7 @@
<string name="show_screen_updates_summary" msgid="2569622766672785529">"Hela fönstret blinkar vid uppdatering"</string>
<string name="show_hw_screen_updates" msgid="4117270979975470789">"Visa visningsuppdatering"</string>
<string name="show_hw_screen_updates_summary" msgid="6506943466625875655">"Visningar blinkar i fönster vid ritningar"</string>
- <string name="show_hw_layers_updates" msgid="5645728765605699821">"Visa maskinvaruskiktuppd."</string>
+ <string name="show_hw_layers_updates" msgid="5645728765605699821">"Visa maskinvaruskiktuppdatering"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Låt maskinvaruskikt blinka grönt vid uppdateringar"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Felsök GPU-överritning"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Inaktivera HW-överlagringar"</string>
@@ -309,7 +310,7 @@
<string name="debug_layout_summary" msgid="2001775315258637682">"Visa gränser för videoklipp, marginaler m.m."</string>
<string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Tvinga fram RTL-layout"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Tvinga fram RTL-skärmlayout (hö–vä) för alla språk"</string>
- <string name="force_msaa" msgid="7920323238677284387">"Force 4x MSAA"</string>
+ <string name="force_msaa" msgid="7920323238677284387">"Tvinga 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Aktivera 4x MSAA i OpenGL ES 2.0-appar"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"Felsök icke-rektangulära urklippsåtgärder"</string>
<string name="track_frame_time" msgid="6094365083096851167">"Profilens HWUI-rendering"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 63d8f34..0b486f7 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Haiwezi kutambaza mitandao"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Hamna"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Imehifadhiwa"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Hujaunganishwa"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Imezimwa"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Haikuweza Kusanidi IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Haijaunganishwa kwa sababu intaneti si thabiti"</string>
@@ -308,7 +309,7 @@
<string name="debug_layout" msgid="5981361776594526155">"Onyesha mipaka ya mpangilio"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"Onyesha mipaka ya picha, kingo, nk."</string>
<string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Lazimisha uelekezaji wa muundo wa RTL"</string>
- <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Lazimisha uelekezaji wa muundo wa skrini kwa RTL kwa lugha zote"</string>
+ <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Lazimisha mkao wa skrini uwe wa kulia kwenda kushoto kwa lugha zote"</string>
<string name="force_msaa" msgid="7920323238677284387">"Lazimisha 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Wezesha 4x MSAA katika programu za OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"Tatua uendeshaji wa klipu usio mstatili"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 6121f03..13741e0 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -23,6 +23,8 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"நெட்வொர்க்குகளுக்கு ஸ்கேன் செய்யப்படவில்லை"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"ஏதுமில்லை"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"சேமிக்கப்பட்டது"</string>
+ <!-- no translation found for wifi_disconnected (8085419869003922556) -->
+ <skip />
<string name="wifi_disabled_generic" msgid="4259794910584943386">"முடக்கப்பட்டது"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP உள்ளமைவில் தோல்வி"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"தரம் குறைவான நெட்வொர்க்கின் காரணமாக, இணைக்கப்படவில்லை"</string>
@@ -213,9 +215,9 @@
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"பூட்லோடரைத் திறக்க அனுமதி"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM திறத்தலை அனுமதிக்கவா?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"எச்சரிக்கை: இந்த அமைப்பு இயக்கப்பட்டிருக்கும்போது, சாதன பாதுகாப்பு அம்சங்கள் இந்தச் சாதனத்தில் இயங்காது."</string>
- <string name="mock_location_app" msgid="7966220972812881854">"போலி இருப்பிடப் பயன்பாட்டைத் தேர்ந்தெடு"</string>
- <string name="mock_location_app_not_set" msgid="809543285495344223">"போலி இருப்பிடப் ஆப்ஸ் அமைக்கப்படவில்லை"</string>
- <string name="mock_location_app_set" msgid="8966420655295102685">"போலி இருப்பிடப் ஆப்ஸ்: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app" msgid="7966220972812881854">"போலி இருப்பிட ஆப்ஸைத் தேர்ந்தெடு"</string>
+ <string name="mock_location_app_not_set" msgid="809543285495344223">"போலி இருப்பிட ஆப்ஸ் அமைக்கப்படவில்லை"</string>
+ <string name="mock_location_app_set" msgid="8966420655295102685">"போலி இருப்பிட ஆப்ஸ்: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="7044075693643009662">"நெட்வொர்க்கிங்"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"வயர்லெஸ் காட்சிக்கான சான்றிதழ்"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"வைஃபை அதிவிவர நுழைவை இயக்கு"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 1db9af4..99affe4 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"నెట్వర్క్ల కోసం స్కాన్ చేయడం సాధ్యపడదు"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"ఏదీ లేదు"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"సేవ్ చేయబడింది"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"డిస్కనెక్ట్ అయ్యింది"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"నిలిపివేయబడింది"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP కాన్ఫిగరేషన్ వైఫల్యం"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"తక్కువ నాణ్యతా నెట్వర్క్ కారణంగా కనెక్ట్ చేయబడలేదు"</string>
@@ -215,7 +216,7 @@
<string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"హెచ్చరిక: ఈ సెట్టింగ్ ఆన్ చేయబడినప్పుడు పరికరం రక్షణ లక్షణాలు ఈ పరికరంలో పని చేయవు."</string>
<string name="mock_location_app" msgid="7966220972812881854">"కృత్రిమ స్థాన యాప్ను ఎంచుకోండి"</string>
<string name="mock_location_app_not_set" msgid="809543285495344223">"అనుకృత స్థాన యాప్ ఏదీ సెట్ చేయబడలేదు"</string>
- <string name="mock_location_app_set" msgid="8966420655295102685">"అనుకృత స్థాన యాప్: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app_set" msgid="8966420655295102685">"కృత్రిమ స్థాన యాప్: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="7044075693643009662">"నెట్వర్కింగ్"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"వైర్లెస్ ప్రదర్శన ప్రామాణీకరణ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi విశదీకృత లాగింగ్ను ప్రారంభించండి"</string>
@@ -301,10 +302,10 @@
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ఓవర్డ్రాను డీబగ్ చేయండి"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW ప్రదర్శనలను నిలిపివేయి"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"స్క్రీన్ కంపాజిటింగ్కు ఎల్లప్పుడూ GPUని ఉపయోగించు"</string>
- <string name="simulate_color_space" msgid="6745847141353345872">"రంగు అంతరాన్ని అనుకరించు"</string>
+ <string name="simulate_color_space" msgid="6745847141353345872">"వివిధ రంగులను అనుకరించు"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"OpenGL ట్రేస్లను ప్రారంభించండి"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"USB ఆడియో రూటింగ్ నిలిపివేయి"</string>
- <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"USB ఆడియో పరికరాలకు ఆటో. రూటింగ్ను నిలిపివేయండి"</string>
+ <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"USB ఆడియో పరికరాలకు ఆటోమేటిక్ రూటింగ్ను నిలిపివేయండి"</string>
<string name="debug_layout" msgid="5981361776594526155">"లేఅవుట్ బౌండ్లు చూపు"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"క్లిప్ సరిహద్దులు, అంచులు మొ. చూపు"</string>
<string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL లేఅవుట్ దిశను నిర్బంధం చేయండి"</string>
@@ -329,7 +330,7 @@
<string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"చెల్లుబాటు అయ్యే ఛానెల్ లేకుండా యాప్ నోటిఫికేషన్ను పోస్ట్ చేస్తున్నప్పుడు స్క్రీన్పై హెచ్చరికను చూపిస్తుంది"</string>
<string name="force_allow_on_external" msgid="3215759785081916381">"యాప్లను బాహ్య నిల్వలో తప్పనిసరిగా అనుమతించు"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"ఏ యాప్ని అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య నిల్వలో సేవ్ చేయడానికి అనుమతిస్తుంది"</string>
- <string name="force_resizable_activities" msgid="8615764378147824985">"కార్యకలాపాలను పరిమాణం మార్చగలిగేలా నిర్బంధించు"</string>
+ <string name="force_resizable_activities" msgid="8615764378147824985">"కార్యకలాపాల విండోల పరిమాణం మార్చగలిగేలా నిర్బంధించు"</string>
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా అన్ని కార్యకలాపాలను పలు రకాల విండోల్లో సరిపోయేట్లు పరిమాణం మార్చగలిగేలా చేస్తుంది."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"స్వతంత్ర రూప విండోలను ప్రారంభించండి"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"ప్రయోగాత్మక స్వతంత్ర రూప విండోల కోసం మద్దతును ప్రారంభిస్తుంది."</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index cad28af..4f8b9e4 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ไม่สามารถสแกนหาเครือข่าย"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"ไม่มี"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"บันทึกแล้ว"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"เลิกเชื่อมต่อแล้ว"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ปิดอยู่"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"การกำหนดค่า IP ล้มเหลว"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ไม่ได้เชื่อมต่อเนื่องจากเครือข่ายคุณภาพต่ำ"</string>
@@ -136,7 +137,7 @@
<string name="accessibility_wifi_signal_full" msgid="7061045677694702">"สัญญาณ Wi-Fi เต็ม"</string>
<string name="accessibility_wifi_security_type_none" msgid="1223747559986205423">"เครือข่ายแบบเปิด"</string>
<string name="accessibility_wifi_security_type_secured" msgid="862921720418885331">"เครือข่ายที่ปลอดภัย"</string>
- <string name="process_kernel_label" msgid="3916858646836739323">"ระบบปฏิบัติการของ Android"</string>
+ <string name="process_kernel_label" msgid="3916858646836739323">"ระบบปฏิบัติการ Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"แอปพลิเคชันที่นำออก"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"แอปพลิเคชันและผู้ใช้ที่นำออก"</string>
<string name="data_usage_ota" msgid="5377889154805560860">"การอัปเดตระบบ"</string>
@@ -213,9 +214,9 @@
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"อนุญาตให้ปลดล็อกตัวโหลดการเปิดเครื่อง"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"อนุญาตการปลดล็อก OEM ไหม"</string>
<string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"คำเตือน: ฟีเจอร์การปกป้องอุปกรณ์จะไม่ทำงานบนอุปกรณ์นี้ขณะที่การตั้งค่านี้เปิดอยู่"</string>
- <string name="mock_location_app" msgid="7966220972812881854">"เลือกแอปจำลองตำแหน่ง"</string>
- <string name="mock_location_app_not_set" msgid="809543285495344223">"ไม่ได้ตั้งค่าแอปจำลองตำแหน่ง"</string>
- <string name="mock_location_app_set" msgid="8966420655295102685">"แอปจำลองตำแหน่ง: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app" msgid="7966220972812881854">"เลือกแอปจำลองสถานที่"</string>
+ <string name="mock_location_app_not_set" msgid="809543285495344223">"ไม่ได้ตั้งค่าแอปจำลองสถานที่"</string>
+ <string name="mock_location_app_set" msgid="8966420655295102685">"แอปจำลองสถานที่: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="7044075693643009662">"เครือข่าย"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"การรับรองการแสดงผลแบบไร้สาย"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"เปิดใช้การบันทึกรายละเอียด Wi-Fi"</string>
@@ -225,7 +226,7 @@
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ปิดใช้การควบคุมระดับเสียงของอุปกรณ์อื่น"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"เวอร์ชันของบลูทูธ AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"เลือกเวอร์ชันของบลูทูธ AVRCP"</string>
- <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ตัวแปลงรหัสเสียงบลูทูธ"</string>
+ <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ตัวแปลงสัญญาณเสียงบลูทูธ"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="8436224899475822557">"ทริกเกอร์การเลือกตัวแปลงรหัส\nเสียงบลูทูธ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"อัตราตัวอย่างเสียงบลูทูธ"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"ทริกเกอร์การเลือกตัวแปลงรหัส\nเสียงบลูทูธ: อัตราตัวอย่าง"</string>
@@ -289,7 +290,7 @@
<string name="strict_mode" msgid="1938795874357830695">"เปิดใช้งานโหมดเข้มงวด"</string>
<string name="strict_mode_summary" msgid="142834318897332338">"กะพริบหน้าจอเมื่อแอปทำงานในชุดข้อความหลักนาน"</string>
<string name="pointer_location" msgid="6084434787496938001">"ตำแหน่งของตัวชี้"</string>
- <string name="pointer_location_summary" msgid="840819275172753713">"การวางซ้อนหน้าจอที่แสดงข้อมูลการแตะ ในปัจจุบัน"</string>
+ <string name="pointer_location_summary" msgid="840819275172753713">"การวางซ้อนหน้าจอที่แสดงข้อมูลการแตะในปัจจุบัน"</string>
<string name="show_touches" msgid="2642976305235070316">"แสดงการแตะ"</string>
<string name="show_touches_summary" msgid="6101183132903926324">"แสดงผลตอบสนองแบบภาพเมื่อแตะ"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"แสดงการอัปเดตพื้นผิว"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 742be8b..bc33509 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Hindi makapag-scan ng mga network"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Wala"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Na-save"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Nadiskonekta"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Naka-disable"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Pagkabigo ng Configuration ng IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Hindi nakakonekta dahil mababa ang kalidad ng network"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 5ebbff1..7afb78a 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ağlar taranamıyor"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Yok"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Kaydedildi"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Bağlı değil"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Devre dışı"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Yapılandırması Hatası"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ağ kalitesi düşük olduğundan bağlanamadı"</string>
@@ -281,13 +282,13 @@
<string name="no_application" msgid="2813387563129153880">"Hiçbiri"</string>
<string name="wait_for_debugger" msgid="1202370874528893091">"Hata ayıklayıcıyı bekle"</string>
<string name="wait_for_debugger_summary" msgid="1766918303462746804">"Hata ayıklanan uygulama, çalıştırılmadan önce hata ayıklayıcının eklenmesini bekler"</string>
- <string name="debug_input_category" msgid="1811069939601180246">"Girdi"</string>
+ <string name="debug_input_category" msgid="1811069939601180246">"Giriş"</string>
<string name="debug_drawing_category" msgid="6755716469267367852">"Çizim"</string>
<string name="debug_hw_drawing_category" msgid="6220174216912308658">"Donanım hızlandırmalı oluşturma"</string>
<string name="media_category" msgid="4388305075496848353">"Medya"</string>
<string name="debug_monitoring_category" msgid="7640508148375798343">"İzleme"</string>
<string name="strict_mode" msgid="1938795874357830695">"Yüksek düzey modu etkin"</string>
- <string name="strict_mode_summary" msgid="142834318897332338">"Uyg. ana işlem parçasında uzun işlem yap. ekr. yakıp söndür"</string>
+ <string name="strict_mode_summary" msgid="142834318897332338">"Uygulamalar ana iş parçacığında uzun işlem yaparken ekranı yanıp söndür"</string>
<string name="pointer_location" msgid="6084434787496938001">"İşaretçi konumu"</string>
<string name="pointer_location_summary" msgid="840819275172753713">"Mevcut dokunmatik verilerini gösteren yer paylaşımı"</string>
<string name="show_touches" msgid="2642976305235070316">"Dokunmayı göster"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index bbb1091..0808456 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Неможливо здійснити сканування мереж"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Немає"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Збережено"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Від’єднано"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Вимкнено"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Помилка конфігурації IP-адреси"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Не під’єднано через низьку якість мережі"</string>
@@ -201,13 +202,13 @@
<string name="tethering_settings_not_available" msgid="6765770438438291012">"Цей користувач не може налаштовувати режим модема"</string>
<string name="apn_settings_not_available" msgid="7873729032165324000">"Цей користувач не може налаштовувати назву точки доступу"</string>
<string name="enable_adb" msgid="7982306934419797485">"Налагодження USB"</string>
- <string name="enable_adb_summary" msgid="4881186971746056635">"Увімк. режим налагодження, коли телефон підключено через USB"</string>
+ <string name="enable_adb_summary" msgid="4881186971746056635">"Вмикати налагодження, коли телефон підключено через USB"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"Скасувати доступ до налагодження USB"</string>
<string name="bugreport_in_power" msgid="7923901846375587241">"Ярлик звіту про помилки"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Показувати в меню живлення кнопку створення звіту про помилки"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Залишати активним"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"Екран не засинатиме під час заряджання"</string>
- <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Увімкнути журнал відстеження інтерфейсу Bluetooth"</string>
+ <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Журнал інтерфейсу Bluetooth"</string>
<string name="bt_hci_snoop_log_summary" msgid="8857606786588106495">"Отримання пакетів Bluetooth. (Змінивши це налаштування, увімкніть Bluetooth.)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"Розблокування виробником"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Дозволити розблокування завантажувача"</string>
@@ -311,7 +312,7 @@
<string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Застосовувати макет письма справа наліво для всіх мов"</string>
<string name="force_msaa" msgid="7920323238677284387">"Примус. запустити 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Увімкнути 4x MSAA в програмах OpenGL ES 2.0"</string>
- <string name="show_non_rect_clip" msgid="505954950474595172">"Налагодити операції непрямокутної обрізки"</string>
+ <string name="show_non_rect_clip" msgid="505954950474595172">"Налагодити непрямокутну обрізку"</string>
<string name="track_frame_time" msgid="6094365083096851167">"Обробка HWUI за профілем"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Увімкнути шари налагодження ГП"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Дозвольте завантажувати шари налагодження ГП для додатків налагодження"</string>
@@ -411,7 +412,7 @@
<string name="disabled" msgid="9206776641295849915">"Вимкнено"</string>
<string name="external_source_trusted" msgid="2707996266575928037">"Дозволено"</string>
<string name="external_source_untrusted" msgid="2677442511837596726">"Заборонено"</string>
- <string name="install_other_apps" msgid="6986686991775883017">"Установлювати невідомі додатки"</string>
+ <string name="install_other_apps" msgid="6986686991775883017">"Встановлювати невідомі додатки"</string>
<string name="home" msgid="3256884684164448244">"Головний екран налаштувань"</string>
<string-array name="battery_labels">
<item msgid="8494684293649631252">"0%"</item>
@@ -461,7 +462,7 @@
<string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Тривалість"</string>
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Запитувати щоразу"</string>
- <string name="zen_mode_forever" msgid="2704305038191592967">"Доки ви не вимкнете"</string>
+ <string name="zen_mode_forever" msgid="2704305038191592967">"Доки не вимкнути"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Щойно"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Цей пристрій"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 7949d9c..8ab1c23 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"نیٹ ورکس کیلئے اسکین نہيں کر سکتے ہیں"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"کوئی نہیں"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"محفوظ کردیا گیا"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"غیر منسلک"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"غیر فعال"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP کنفیگریشن کی ناکامی"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"کم معیاری نیٹ ورک کی وجہ سے منسلک نہیں ہے"</string>
@@ -330,7 +331,7 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"بیرونی پر ایپس کو زبردستی اجازت دیں"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"سرگرمیوں کو ری سائز ایبل بنائیں"</string>
- <string name="force_resizable_activities_summary" msgid="6667493494706124459">"manifest اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بنائیں۔"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"مینی فیسٹ اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بنائیں۔"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"freeform ونڈوز فعال کریں"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"تجرباتی فری فارم ونڈوز کیلئے سپورٹ فعال کریں۔"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ڈیسک ٹاپ کا بیک اپ پاس ورڈ"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 4decd09..2bcb450 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tarmoqlarni tekshirib chiqishni iloji bo‘lmadi"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Hech qanday"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saqlandi"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Ulanmagan"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Yoqilmagan"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP manzilini sozlab bo‘lmadi"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Sifatsiz tarmoq sababli ulanib bo‘lmadi"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index ee8283a..2ac9a9b 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Không thể dò tìm mạng"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Không"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Đã lưu"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Đã ngắt kết nối"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Đã tắt"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Lỗi cấu hình IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Không được kết nối do mạng chất lượng kém"</string>
@@ -153,7 +154,7 @@
<string name="launch_defaults_none" msgid="4241129108140034876">"Chưa đặt mặc định"</string>
<string name="tts_settings" msgid="8186971894801348327">"Cài đặt chuyển văn bản sang lời nói"</string>
<string name="tts_settings_title" msgid="1237820681016639683">"Đầu ra văn bản thành giọng nói"</string>
- <string name="tts_default_rate_title" msgid="6030550998379310088">"Tốc độ nói"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Tốc độ lời nói"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Tốc độ đọc văn bản"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"Độ cao"</string>
<string name="tts_default_pitch_summary" msgid="1944885882882650009">"Ảnh hưởng đến âm điệu giọng nói được tổng hợp"</string>
@@ -206,7 +207,7 @@
<string name="bugreport_in_power" msgid="7923901846375587241">"Phím tắt báo cáo lỗi"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Hiển thị một nút trong menu nguồn để báo cáo lỗi"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Không khóa màn hình"</string>
- <string name="keep_screen_on_summary" msgid="2173114350754293009">"Màn hình sẽ không bao giờ chuyển sang chế độ nghỉ khi sạc"</string>
+ <string name="keep_screen_on_summary" msgid="2173114350754293009">"Màn hình sẽ không bao giờ chuyển sang chế độ ngủ khi sạc"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"Bật nhật ký theo dõi HCI Bluetooth"</string>
<string name="bt_hci_snoop_log_summary" msgid="8857606786588106495">"Chụp các gói Bluetooth. (Chuyển đổi Bluetooth sau khi thay đổi tùy chọn cài đặt này)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"Mở khóa OEM"</string>
@@ -333,9 +334,9 @@
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"Cho phép thay đổi kích thước của tất cả các hoạt động cho nhiều cửa sổ, bất kể giá trị tệp kê khai là gì."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Bật cửa sổ dạng tự do"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"Bật tính năng hỗ trợ cửa sổ dạng tự do thử nghiệm."</string>
- <string name="local_backup_password_title" msgid="3860471654439418822">"Mật khẩu sao lưu của máy tính"</string>
- <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Sao lưu toàn bộ máy tính hiện không được bảo vệ"</string>
- <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Nhấn để thay đổi hoặc xóa mật khẩu dành cho sao lưu toàn bộ tới máy tính"</string>
+ <string name="local_backup_password_title" msgid="3860471654439418822">"Mật khẩu sao lưu vào máy tính"</string>
+ <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Các bản sao lưu đầy đủ vào máy tính hiện không được bảo vệ"</string>
+ <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Nhấn để thay đổi hoặc xóa mật khẩu dành cho các bản sao lưu đầy đủ vào máy tính"</string>
<string name="local_backup_password_toast_success" msgid="582016086228434290">"Đã đặt mật khẩu sao lưu mới"</string>
<string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"Mật khẩu mới và xác nhận không khớp"</string>
<string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Đặt mật khẩu sao lưu không thành công"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 93d923a9..8685c10 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"无法扫描网络"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"无"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"已保存"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"已断开连接"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 配置失败"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"网络质量较差,因此未连接"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index c5b513e..653a39b 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"無法掃瞄網絡"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"無"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"已儲存"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"已解除連接"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 設定失敗"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"網絡品質欠佳,因此無法連線"</string>
@@ -236,7 +237,7 @@
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"藍牙音訊 LDAC 編解碼器:播放品質"</string>
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"觸發藍牙音訊 LDAC\n編解碼器選項:播放品質"</string>
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"正在串流:<xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
- <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"不公開的網域名稱系統 (DNS)"</string>
+ <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"私人 DNS"</string>
<string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"選取私人網域名稱系統 (DNS) 模式"</string>
<string name="private_dns_mode_off" msgid="8236575187318721684">"停用"</string>
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"自動"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index d1e8b64..1201938 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"無法掃描網路"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"無"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"已儲存"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"已中斷連線"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 設定失敗"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"網路品質不佳,因此未連線"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 83ea4c0..9ea73fa 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -23,6 +23,7 @@
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ayikwazi ukuhlola amanethiwekhi"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"Lutho"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Kulondoloziwe"</string>
+ <string name="wifi_disconnected" msgid="8085419869003922556">"Inqamukile"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Akusebenzi"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ukwehluleka kokulungiswa kwe-IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ayixhunyiwe ngenxa yenethiwekhi yekhwalithi ephansi"</string>
diff --git a/packages/SettingsLib/res/values/colors.xml b/packages/SettingsLib/res/values/colors.xml
index 209b2cb..5e8779f 100644
--- a/packages/SettingsLib/res/values/colors.xml
+++ b/packages/SettingsLib/res/values/colors.xml
@@ -35,4 +35,8 @@
<color name="bt_color_bg_5">#fdcfe8</color> <!-- Material Pink 100 -->
<color name="bt_color_bg_6">#e9d2fd</color> <!-- Material Purple 100 -->
<color name="bt_color_bg_7">#cbf0f8</color> <!-- Material Cyan 100 -->
+
+
+ <color name="dark_mode_icon_color_single_tone">#99000000</color>
+ <color name="light_mode_icon_color_single_tone">#ffffff</color>
</resources>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 2cb9d4b..d10e034 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -88,8 +88,6 @@
<!-- SignalDrawable -->
<dimen name="signal_icon_size">15dp</dimen>
- <!-- How far to inset the rounded edges -->
- <dimen name="stat_sys_mobile_signal_circle_inset">0.9dp</dimen>
<!-- Size of nearby icon -->
<dimen name="bt_nearby_icon_size">24dp</dimen>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index e02709e..5eaa163 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -707,7 +707,9 @@
private long getTotalInternalSize(PackageStats ps) {
if (ps != null) {
- return ps.codeSize + ps.dataSize;
+ // We subtract the cache size because the system can clear it automatically and
+ // |dataSize| is a superset of |cacheSize|.
+ return ps.codeSize + ps.dataSize - ps.cacheSize;
}
return SIZE_INVALID;
}
@@ -715,7 +717,7 @@
private long getTotalExternalSize(PackageStats ps) {
if (ps != null) {
// We also include the cache size here because for non-emulated
- // we don't automtically clean cache files.
+ // we don't automatically clean cache files.
return ps.externalCodeSize + ps.externalDataSize
+ ps.externalCacheSize
+ ps.externalMediaSize + ps.externalObbSize;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index ff34578..1d351a5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -50,6 +50,8 @@
// See mConnectAttempted
private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000;
+ // Some Hearing Aids (especially the 2nd device) needs more time to do service discovery
+ private static final long MAX_HEARING_AIDS_DELAY_FOR_AUTO_CONNECT = 15000;
private static final long MAX_HOGP_DELAY_FOR_AUTO_CONNECT = 30000;
private final Context mContext;
@@ -223,7 +225,7 @@
// various profiles
// If UUIDs are not available yet, connect will be happen
// upon arrival of the ACTION_UUID intent.
- Log.d(TAG, "No profiles. Maybe we will connect later");
+ Log.d(TAG, "No profiles. Maybe we will connect later for device " + mDevice);
return;
}
@@ -608,10 +610,12 @@
long timeout = MAX_UUID_DELAY_FOR_AUTO_CONNECT;
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp)) {
timeout = MAX_HOGP_DELAY_FOR_AUTO_CONNECT;
+ } else if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HearingAid)) {
+ timeout = MAX_HEARING_AIDS_DELAY_FOR_AUTO_CONNECT;
}
if (BluetoothUtils.D) {
- Log.d(TAG, "onUuidChanged: Time since last connect"
+ Log.d(TAG, "onUuidChanged: Time since last connect="
+ (SystemClock.elapsedRealtime() - mConnectAttempted));
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
index 4bd1bbb..98eb573 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
@@ -19,25 +19,28 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
-import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Path.FillType;
-import android.graphics.Path.Op;
-import android.graphics.PointF;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableWrapper;
import android.os.Handler;
+import android.telephony.SignalStrength;
import android.util.LayoutDirection;
import com.android.settingslib.R;
import com.android.settingslib.Utils;
-public class SignalDrawable extends Drawable {
+/**
+ * Drawable displaying a mobile cell signal indicator.
+ */
+public class SignalDrawable extends DrawableWrapper {
private static final String TAG = "SignalDrawable";
@@ -48,11 +51,7 @@
private static final float CUT_OUT = 7.9f / VIEWPORT;
private static final float DOT_SIZE = 3f / VIEWPORT;
- private static final float DOT_PADDING = 1f / VIEWPORT;
- private static final float DOT_CUT_WIDTH = (DOT_SIZE * 3) + (DOT_PADDING * 5);
- private static final float DOT_CUT_HEIGHT = (DOT_SIZE * 1) + (DOT_PADDING * 1);
-
- private static final float[] FIT = {2.26f, -3.02f, 1.76f};
+ private static final float DOT_PADDING = 1.5f / VIEWPORT;
// All of these are masks to push all of the drawable state into one int for easy callbacks
// and flow through sysui.
@@ -61,11 +60,8 @@
private static final int NUM_LEVEL_MASK = 0xff << NUM_LEVEL_SHIFT;
private static final int STATE_SHIFT = 16;
private static final int STATE_MASK = 0xff << STATE_SHIFT;
- private static final int STATE_NONE = 0;
- private static final int STATE_EMPTY = 1;
private static final int STATE_CUT = 2;
private static final int STATE_CARRIER_CHANGE = 3;
- private static final int STATE_AIRPLANE = 4;
private static final long DOT_DELAY = 1000;
@@ -84,76 +80,30 @@
{-1.9f / VIEWPORT, -1.9f / VIEWPORT},
};
- // Rounded corners are achieved by arcing a circle of radius `R` from its tangent points along
- // the curve (curve ≡ triangle). On the top and left corners of the triangle, the tangents are
- // as follows:
- // 1) Along the straight lines (y = 0 and x = width):
- // Ps = circleOffset + R
- // 2) Along the diagonal line (y = x):
- // Pd = √((Ps^2) / 2)
- // or (remember: sin(π/4) ≈ 0.7071)
- // Pd = (circleOffset + R - 0.7071, height - R - 0.7071)
- // Where Pd is the (x,y) coords of the point that intersects the circle at the bottom
- // left of the triangle
- private static final float RADIUS_RATIO = 0.75f / 17f;
- private static final float DIAG_OFFSET_MULTIPLIER = 0.707107f;
- // How far the circle defining the corners is inset from the edges
- private final float mAppliedCornerInset;
-
- private static final float INV_TAN = 1f / (float) Math.tan(Math.PI / 8f);
- private static final float CUT_WIDTH_DP = 1f / 12f;
-
- // Where the top and left points of the triangle would be if not for rounding
- private final PointF mVirtualTop = new PointF();
- private final PointF mVirtualLeft = new PointF();
-
- private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mForegroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- private final int mDarkModeBackgroundColor;
+ private final Paint mTransparentPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final int mDarkModeFillColor;
- private final int mLightModeBackgroundColor;
private final int mLightModeFillColor;
- private final Path mFullPath = new Path();
+ private final Path mCutoutPath = new Path();
private final Path mForegroundPath = new Path();
private final Path mXPath = new Path();
- // Cut out when STATE_EMPTY
- private final Path mCutPath = new Path();
- // Draws the slash when in airplane mode
- private final SlashArtist mSlash = new SlashArtist();
private final Handler mHandler;
- private float mOldDarkIntensity = -1;
- private float mNumLevels = 1;
- private int mIntrinsicSize;
- private int mLevel;
- private int mState;
- private boolean mVisible;
+ private float mDarkIntensity = -1;
+ private final int mIntrinsicSize;
private boolean mAnimating;
private int mCurrentDot;
public SignalDrawable(Context context) {
- mDarkModeBackgroundColor =
- Utils.getColorStateListDefaultColor(context,
- R.color.dark_mode_icon_color_dual_tone_background);
- mDarkModeFillColor =
- Utils.getColorStateListDefaultColor(context,
- R.color.dark_mode_icon_color_dual_tone_fill);
- mLightModeBackgroundColor =
- Utils.getColorStateListDefaultColor(context,
- R.color.light_mode_icon_color_dual_tone_background);
- mLightModeFillColor =
- Utils.getColorStateListDefaultColor(context,
- R.color.light_mode_icon_color_dual_tone_fill);
+ super(context.getDrawable(com.android.internal.R.drawable.ic_signal_cellular));
+ mDarkModeFillColor = Utils.getColorStateListDefaultColor(context,
+ R.color.dark_mode_icon_color_single_tone);
+ mLightModeFillColor = Utils.getColorStateListDefaultColor(context,
+ R.color.light_mode_icon_color_single_tone);
mIntrinsicSize = context.getResources().getDimensionPixelSize(R.dimen.signal_icon_size);
-
+ mTransparentPaint.setColor(context.getColor(android.R.color.transparent));
+ mTransparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
mHandler = new Handler();
setDarkIntensity(0);
-
- mAppliedCornerInset = context.getResources()
- .getDimensionPixelSize(R.dimen.stat_sys_mobile_signal_circle_inset);
- }
-
- public void setIntrinsicSize(int size) {
- mIntrinsicSize = size;
}
@Override
@@ -166,21 +116,8 @@
return mIntrinsicSize;
}
- public void setNumLevels(int levels) {
- if (levels == mNumLevels) return;
- mNumLevels = levels;
- invalidateSelf();
- }
-
- private void setSignalState(int state) {
- if (state == mState) return;
- mState = state;
- updateAnimation();
- invalidateSelf();
- }
-
private void updateAnimation() {
- boolean shouldAnimate = (mState == STATE_CARRIER_CHANGE) && mVisible;
+ boolean shouldAnimate = isInState(STATE_CARRIER_CHANGE) && isVisible();
if (shouldAnimate == mAnimating) return;
mAnimating = shouldAnimate;
if (shouldAnimate) {
@@ -191,33 +128,33 @@
}
@Override
- protected boolean onLevelChange(int state) {
- setNumLevels(getNumLevels(state));
- setSignalState(getState(state));
- int level = getLevel(state);
- if (level != mLevel) {
- mLevel = level;
- invalidateSelf();
- }
+ protected boolean onLevelChange(int packedState) {
+ super.onLevelChange(unpackLevel(packedState));
+ updateAnimation();
+ setTintList(ColorStateList.valueOf(mForegroundPaint.getColor()));
return true;
}
- public void setColors(int background, int foreground) {
- int colorBackground = mPaint.getColor();
- int colorForeground = mForegroundPaint.getColor();
- mPaint.setColor(background);
- mForegroundPaint.setColor(foreground);
- if (colorBackground != background || colorForeground != foreground) invalidateSelf();
+ private int unpackLevel(int packedState) {
+ int numBins = (packedState & NUM_LEVEL_MASK) >> NUM_LEVEL_SHIFT;
+ int levelOffset = numBins == (SignalStrength.NUM_SIGNAL_STRENGTH_BINS + 1) ? 10 : 0;
+ int level = (packedState & LEVEL_MASK);
+ return level + levelOffset;
}
public void setDarkIntensity(float darkIntensity) {
- if (darkIntensity == mOldDarkIntensity) {
+ if (darkIntensity == mDarkIntensity) {
return;
}
- mPaint.setColor(getBackgroundColor(darkIntensity));
- mForegroundPaint.setColor(getFillColor(darkIntensity));
- mOldDarkIntensity = darkIntensity;
- invalidateSelf();
+ setTintList(ColorStateList.valueOf(getFillColor(darkIntensity)));
+ }
+
+ @Override
+ public void setTintList(ColorStateList tint) {
+ super.setTintList(tint);
+ int colorForeground = mForegroundPaint.getColor();
+ mForegroundPaint.setColor(tint.getDefaultColor());
+ if (colorForeground != mForegroundPaint.getColor()) invalidateSelf();
}
private int getFillColor(float darkIntensity) {
@@ -225,11 +162,6 @@
darkIntensity, mLightModeFillColor, mDarkModeFillColor);
}
- private int getBackgroundColor(float darkIntensity) {
- return getColorForDarkIntensity(
- darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor);
- }
-
private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) {
return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor);
}
@@ -242,6 +174,7 @@
@Override
public void draw(@NonNull Canvas canvas) {
+ canvas.saveLayer(null, null);
final float width = getBounds().width();
final float height = getBounds().height();
@@ -252,113 +185,32 @@
canvas.translate(width, 0);
canvas.scale(-1.0f, 1.0f);
}
- mFullPath.reset();
- mFullPath.setFillType(FillType.WINDING);
+ super.draw(canvas);
+ mCutoutPath.reset();
+ mCutoutPath.setFillType(FillType.WINDING);
final float padding = Math.round(PAD * width);
- final float cornerRadius = RADIUS_RATIO * height;
- // Offset from circle where the hypotenuse meets the circle
- final float diagOffset = DIAG_OFFSET_MULTIPLIER * cornerRadius;
- // 1 - Bottom right, above corner
- mFullPath.moveTo(width - padding, height - padding - cornerRadius);
- // 2 - Line to top right, below corner
- mFullPath.lineTo(width - padding, padding + cornerRadius + mAppliedCornerInset);
- // 3 - Arc to top right, on hypotenuse
- mFullPath.arcTo(
- width - padding - (2 * cornerRadius),
- padding + mAppliedCornerInset,
- width - padding,
- padding + mAppliedCornerInset + (2 * cornerRadius),
- 0.f, -135.f, false
- );
- // 4 - Line to bottom left, on hypotenuse
- mFullPath.lineTo(padding + mAppliedCornerInset + cornerRadius - diagOffset,
- height - padding - cornerRadius - diagOffset);
- // 5 - Arc to bottom left, on leg
- mFullPath.arcTo(
- padding + mAppliedCornerInset,
- height - padding - (2 * cornerRadius),
- padding + mAppliedCornerInset + ( 2 * cornerRadius),
- height - padding,
- -135.f, -135.f, false
- );
- // 6 - Line to bottom rght, before corner
- mFullPath.lineTo(width - padding - cornerRadius, height - padding);
- // 7 - Arc to beginning (bottom right, above corner)
- mFullPath.arcTo(
- width - padding - (2 * cornerRadius),
- height - padding - (2 * cornerRadius),
- width - padding,
- height - padding,
- 90.f, -90.f, false
- );
-
- if (mState == STATE_CARRIER_CHANGE) {
- float cutWidth = (DOT_CUT_WIDTH * width);
- float cutHeight = (DOT_CUT_HEIGHT * width);
+ if (isInState(STATE_CARRIER_CHANGE)) {
float dotSize = (DOT_SIZE * height);
float dotPadding = (DOT_PADDING * height);
-
- mFullPath.moveTo(width - padding, height - padding);
- mFullPath.rLineTo(-cutWidth, 0);
- mFullPath.rLineTo(0, -cutHeight);
- mFullPath.rLineTo(cutWidth, 0);
- mFullPath.rLineTo(0, cutHeight);
- float dotSpacing = dotPadding * 2 + dotSize;
+ float dotSpacing = dotPadding + dotSize;
float x = width - padding - dotSize;
float y = height - padding - dotSize;
mForegroundPath.reset();
- drawDot(mFullPath, mForegroundPath, x, y, dotSize, 2);
- drawDot(mFullPath, mForegroundPath, x - dotSpacing, y, dotSize, 1);
- drawDot(mFullPath, mForegroundPath, x - dotSpacing * 2, y, dotSize, 0);
- } else if (mState == STATE_CUT) {
+ drawDotAndPadding(x, y, dotPadding, dotSize, 2);
+ drawDotAndPadding(x - dotSpacing, y, dotPadding, dotSize, 1);
+ drawDotAndPadding(x - dotSpacing * 2, y, dotPadding, dotSize, 0);
+ canvas.drawPath(mCutoutPath, mTransparentPaint);
+ canvas.drawPath(mForegroundPath, mForegroundPaint);
+ } else if (isInState(STATE_CUT)) {
float cut = (CUT_OUT * width);
- mFullPath.moveTo(width - padding, height - padding);
- mFullPath.rLineTo(-cut, 0);
- mFullPath.rLineTo(0, -cut);
- mFullPath.rLineTo(cut, 0);
- mFullPath.rLineTo(0, cut);
- }
-
- if (mState == STATE_EMPTY) {
- // Where the corners would be if this were a real triangle
- mVirtualTop.set(
- width - padding,
- (padding + cornerRadius + mAppliedCornerInset) - (INV_TAN * cornerRadius));
- mVirtualLeft.set(
- (padding + cornerRadius + mAppliedCornerInset) - (INV_TAN * cornerRadius),
- height - padding);
-
- final float cutWidth = CUT_WIDTH_DP * height;
- final float cutDiagInset = cutWidth * INV_TAN;
-
- // Cut out a smaller triangle from the center of mFullPath
- mCutPath.reset();
- mCutPath.setFillType(FillType.WINDING);
- mCutPath.moveTo(width - padding - cutWidth, height - padding - cutWidth);
- mCutPath.lineTo(width - padding - cutWidth, mVirtualTop.y + cutDiagInset);
- mCutPath.lineTo(mVirtualLeft.x + cutDiagInset, height - padding - cutWidth);
- mCutPath.lineTo(width - padding - cutWidth, height - padding - cutWidth);
-
- // Draw empty state as only background
- mForegroundPath.reset();
- mFullPath.op(mCutPath, Path.Op.DIFFERENCE);
- } else if (mState == STATE_AIRPLANE) {
- // Airplane mode is slashed, fully drawn background
- mForegroundPath.reset();
- mSlash.draw((int) height, (int) width, canvas, mPaint);
- } else if (mState != STATE_CARRIER_CHANGE) {
- mForegroundPath.reset();
- int sigWidth = Math.round(calcFit(mLevel / (mNumLevels - 1)) * (width - 2 * padding));
- mForegroundPath.addRect(padding, padding, padding + sigWidth, height - padding,
- Direction.CW);
- mForegroundPath.op(mFullPath, Op.INTERSECT);
- }
-
- canvas.drawPath(mFullPath, mPaint);
- canvas.drawPath(mForegroundPath, mForegroundPaint);
- if (mState == STATE_CUT) {
+ mCutoutPath.moveTo(width - padding, height - padding);
+ mCutoutPath.rLineTo(-cut, 0);
+ mCutoutPath.rLineTo(0, -cut);
+ mCutoutPath.rLineTo(cut, 0);
+ mCutoutPath.rLineTo(0, cut);
+ canvas.drawPath(mCutoutPath, mTransparentPaint);
mXPath.reset();
mXPath.moveTo(X_PATH[0][0] * width, X_PATH[0][1] * height);
for (int i = 1; i < X_PATH.length; i++) {
@@ -369,57 +221,37 @@
if (isRtl) {
canvas.restore();
}
+ canvas.restore();
}
- private void drawDot(Path fullPath, Path foregroundPath, float x, float y, float dotSize,
- int i) {
- Path p = (i == mCurrentDot) ? foregroundPath : fullPath;
- p.addRect(x, y, x + dotSize, y + dotSize, Direction.CW);
- }
-
- // This is a fit line based on previous values of provided in assets, but if
- // you look at the a plot of this actual fit, it makes a lot of sense, what it does
- // is compress the areas that are very visually easy to see changes (the middle sections)
- // and spread out the sections that are hard to see (each end of the icon).
- // The current fit is cubic, but pretty easy to change the way the code is written (just add
- // terms to the end of FIT).
- private float calcFit(float v) {
- float ret = 0;
- float t = v;
- for (int i = 0; i < FIT.length; i++) {
- ret += FIT[i] * t;
- t *= v;
+ private void drawDotAndPadding(float x, float y,
+ float dotPadding, float dotSize, int i) {
+ if (i == mCurrentDot) {
+ // Draw dot
+ mForegroundPath.addRect(x, y, x + dotSize, y + dotSize, Direction.CW);
+ // Draw dot padding
+ mCutoutPath.addRect(x - dotPadding, y - dotPadding, x + dotSize + dotPadding,
+ y + dotSize + dotPadding, Direction.CW);
}
- return ret;
- }
-
- @Override
- public int getAlpha() {
- return mPaint.getAlpha();
}
@Override
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
- mPaint.setAlpha(alpha);
+ super.setAlpha(alpha);
mForegroundPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
- mPaint.setColorFilter(colorFilter);
+ super.setColorFilter(colorFilter);
mForegroundPaint.setColorFilter(colorFilter);
}
@Override
- public int getOpacity() {
- return 255;
- }
-
- @Override
public boolean setVisible(boolean visible, boolean restart) {
- mVisible = visible;
+ boolean changed = super.setVisible(visible, restart);
updateAnimation();
- return super.setVisible(visible, restart);
+ return changed;
}
private final Runnable mChangeDot = new Runnable() {
@@ -433,92 +265,32 @@
}
};
- public static int getLevel(int fullState) {
- return fullState & LEVEL_MASK;
+ /**
+ * Returns whether this drawable is in the specified state.
+ *
+ * @param state must be one of {@link #STATE_CARRIER_CHANGE} or {@link #STATE_CUT}
+ */
+ private boolean isInState(int state) {
+ return getState(getLevel()) == state;
}
public static int getState(int fullState) {
return (fullState & STATE_MASK) >> STATE_SHIFT;
}
- public static int getNumLevels(int fullState) {
- return (fullState & NUM_LEVEL_MASK) >> NUM_LEVEL_SHIFT;
- }
-
public static int getState(int level, int numLevels, boolean cutOut) {
return ((cutOut ? STATE_CUT : 0) << STATE_SHIFT)
| (numLevels << NUM_LEVEL_SHIFT)
| level;
}
+ /** Returns the state representing empty mobile signal with the given number of levels. */
+ public static int getEmptyState(int numLevels) {
+ return getState(0, numLevels, true);
+ }
+
+ /** Returns the state representing carrier change with the given number of levels. */
public static int getCarrierChangeState(int numLevels) {
return (STATE_CARRIER_CHANGE << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
}
-
- public static int getEmptyState(int numLevels) {
- return (STATE_EMPTY << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
- }
-
- public static int getAirplaneModeState(int numLevels) {
- return (STATE_AIRPLANE << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
- }
-
- private final class SlashArtist {
- private static final float CORNER_RADIUS = 1f;
- // These values are derived in un-rotated (vertical) orientation
- private static final float SLASH_WIDTH = 1.8384776f;
- private static final float SLASH_HEIGHT = 22f;
- private static final float CENTER_X = 10.65f;
- private static final float CENTER_Y = 15.869239f;
- private static final float SCALE = 24f;
-
- // Bottom is derived during animation
- private static final float LEFT = (CENTER_X - (SLASH_WIDTH / 2)) / SCALE;
- private static final float TOP = (CENTER_Y - (SLASH_HEIGHT / 2)) / SCALE;
- private static final float RIGHT = (CENTER_X + (SLASH_WIDTH / 2)) / SCALE;
- private static final float BOTTOM = (CENTER_Y + (SLASH_HEIGHT / 2)) / SCALE;
- // Draw the slash washington-monument style; rotate to no-u-turn style
- private static final float ROTATION = -45f;
-
- private final Path mPath = new Path();
- private final RectF mSlashRect = new RectF();
-
- void draw(int height, int width, @NonNull Canvas canvas, Paint paint) {
- Matrix m = new Matrix();
- final float radius = scale(CORNER_RADIUS, width);
- updateRect(
- scale(LEFT, width),
- scale(TOP, height),
- scale(RIGHT, width),
- scale(BOTTOM, height));
-
- mPath.reset();
- // Draw the slash vertically
- mPath.addRoundRect(mSlashRect, radius, radius, Direction.CW);
- m.setRotate(ROTATION, width / 2, height / 2);
- mPath.transform(m);
- canvas.drawPath(mPath, paint);
-
- // Rotate back to vertical, and draw the cut-out rect next to this one
- m.setRotate(-ROTATION, width / 2, height / 2);
- mPath.transform(m);
- m.setTranslate(mSlashRect.width(), 0);
- mPath.transform(m);
- mPath.addRoundRect(mSlashRect, radius, radius, Direction.CW);
- m.setRotate(ROTATION, width / 2, height / 2);
- mPath.transform(m);
- canvas.clipOutPath(mPath);
- }
-
- void updateRect(float left, float top, float right, float bottom) {
- mSlashRect.left = left;
- mSlashRect.top = top;
- mSlashRect.right = right;
- mSlashRect.bottom = bottom;
- }
-
- private float scale(float frac, int width) {
- return frac * width;
- }
- }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
index b8e1251..6fd8749 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
@@ -18,11 +18,11 @@
import android.app.AppOpsManager;
import android.content.Context;
+import android.content.PermissionChecker;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
-import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.format.DateUtils;
@@ -48,10 +48,15 @@
private static final long RECENT_TIME_INTERVAL_MILLIS = DateUtils.DAY_IN_MILLIS;
@VisibleForTesting
- static final int[] LOCATION_OPS = new int[] {
+ static final int[] LOCATION_REQUEST_OPS = new int[]{
AppOpsManager.OP_MONITOR_LOCATION,
AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION,
};
+ @VisibleForTesting
+ static final int[] LOCATION_PERMISSION_OPS = new int[]{
+ AppOpsManager.OP_FINE_LOCATION,
+ AppOpsManager.OP_COARSE_LOCATION,
+ };
private final PackageManager mPackageManager;
private final Context mContext;
@@ -67,11 +72,13 @@
* Fills a list of applications which queried location recently within specified time.
* Apps are sorted by recency. Apps with more recent location requests are in the front.
*/
- public List<Request> getAppList() {
+ public List<Request> getAppList(boolean showSystemApps) {
+ // Retrieve a location usage list from AppOps
+ PackageManager pm = mContext.getPackageManager();
// Retrieve a location usage list from AppOps
AppOpsManager aoManager =
(AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
- List<AppOpsManager.PackageOps> appOps = aoManager.getPackagesForOps(LOCATION_OPS);
+ List<AppOpsManager.PackageOps> appOps = aoManager.getPackagesForOps(LOCATION_REQUEST_OPS);
final int appOpsCount = appOps != null ? appOps.size() : 0;
@@ -83,26 +90,58 @@
for (int i = 0; i < appOpsCount; ++i) {
AppOpsManager.PackageOps ops = appOps.get(i);
- // Don't show the Android System in the list - it's not actionable for the user.
- // Also don't show apps belonging to background users except managed users.
String packageName = ops.getPackageName();
int uid = ops.getUid();
- int userId = UserHandle.getUserId(uid);
- boolean isAndroidOs =
- (uid == Process.SYSTEM_UID) && ANDROID_SYSTEM_PACKAGE_NAME.equals(packageName);
- if (isAndroidOs || !profiles.contains(new UserHandle(userId))) {
+ final UserHandle user = UserHandle.getUserHandleForUid(uid);
+
+ // Don't show apps belonging to background users except managed users.
+ if (!profiles.contains(user)) {
continue;
}
- Request request = getRequestFromOps(now, ops);
- if (request != null) {
- requests.add(request);
+
+ // Don't show apps that do not have user sensitive location permissions
+ boolean showApp = true;
+ if (!showSystemApps) {
+ for (int op : LOCATION_PERMISSION_OPS) {
+ final String permission = AppOpsManager.opToPermission(op);
+ final int permissionFlags = pm.getPermissionFlags(permission, packageName,
+ user);
+ if (PermissionChecker.checkPermission(mContext, permission, -1, uid,
+ packageName)
+ == PermissionChecker.PERMISSION_GRANTED) {
+ if ((permissionFlags
+ & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED)
+ == 0) {
+ showApp = false;
+ break;
+ }
+ } else {
+ if ((permissionFlags
+ & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) == 0) {
+ showApp = false;
+ break;
+ }
+ }
+ }
+ }
+ if (showApp) {
+ Request request = getRequestFromOps(now, ops);
+ if (request != null) {
+ requests.add(request);
+ }
}
}
return requests;
}
- public List<Request> getAppListSorted() {
- List<Request> requests = getAppList();
+ /**
+ * Gets a list of apps that requested for location recently, sorting by recency.
+ *
+ * @param showSystemApps whether includes system apps in the list.
+ * @return the list of apps that recently requested for location.
+ */
+ public List<Request> getAppListSorted(boolean showSystemApps) {
+ List<Request> requests = getAppList(showSystemApps);
// Sort the list of Requests by recency. Most recent request first.
Collections.sort(requests, Collections.reverseOrder(new Comparator<Request>() {
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
index 151aa8d..008943c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
@@ -198,6 +198,11 @@
}
@Override
+ public void onAudioModeChanged() {
+ dispatchDataChanged();
+ }
+
+ @Override
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
if (isCachedDeviceConnected(cachedDevice)) {
addMediaDevice(cachedDevice);
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
index 8cb252e..f30de13 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
@@ -42,6 +42,8 @@
import android.util.Range;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import java.time.ZonedDateTime;
import java.util.Iterator;
@@ -57,7 +59,6 @@
PERIOD_BUILDER, Locale.getDefault());
private final Context mContext;
- private final TelephonyManager mTelephonyManager;
private final ConnectivityManager mConnectivityManager;
private final INetworkStatsService mStatsService;
private final NetworkPolicyManager mPolicyManager;
@@ -70,7 +71,6 @@
public DataUsageController(Context context) {
mContext = context;
- mTelephonyManager = TelephonyManager.from(context);
mConnectivityManager = ConnectivityManager.from(context);
mStatsService = INetworkStatsService.Stub.asInterface(
ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
@@ -115,7 +115,8 @@
return warn("no subscriber id");
}
NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
- template = NetworkTemplate.normalize(template, mTelephonyManager.getMergedSubscriberIds());
+ template = NetworkTemplate.normalize(template, getTelephonyManager()
+ .getMergedSubscriberIds());
return getDataUsageInfo(template);
}
@@ -174,9 +175,7 @@
private long getUsageLevel(NetworkTemplate template, long start, long end) {
try {
- final Bucket bucket = mNetworkStatsManager.querySummaryForDevice(
- getNetworkType(template), getActiveSubscriberId(),
- start, end);
+ final Bucket bucket = mNetworkStatsManager.querySummaryForDevice(template, start, end);
if (bucket != null) {
return bucket.getRxBytes() + bucket.getTxBytes();
}
@@ -212,9 +211,29 @@
.append(']').toString();
}
+ @VisibleForTesting
+ public TelephonyManager getTelephonyManager() {
+ int subscriptionId = mSubscriptionId;
+
+ // If mSubscriptionId is invalid, get default data sub.
+ if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
+ subscriptionId = SubscriptionManager.getDefaultDataSubscriptionId();
+ }
+
+ // If data sub is also invalid, get any active sub.
+ if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
+ int[] activeSubIds = SubscriptionManager.from(mContext).getActiveSubscriptionIdList();
+ if (!ArrayUtils.isEmpty(activeSubIds)) {
+ subscriptionId = activeSubIds[0];
+ }
+ }
+
+ return TelephonyManager.from(mContext).createForSubscriptionId(subscriptionId);
+ }
+
public void setMobileDataEnabled(boolean enabled) {
Log.d(TAG, "setMobileDataEnabled: enabled=" + enabled);
- mTelephonyManager.setDataEnabled(enabled);
+ getTelephonyManager().setDataEnabled(enabled);
if (mCallback != null) {
mCallback.onMobileDataEnabled(enabled);
}
@@ -223,11 +242,11 @@
public boolean isMobileDataSupported() {
// require both supported network and ready SIM
return mConnectivityManager.isNetworkSupported(TYPE_MOBILE)
- && mTelephonyManager.getSimState() == SIM_STATE_READY;
+ && getTelephonyManager().getSimState() == SIM_STATE_READY;
}
public boolean isMobileDataEnabled() {
- return mTelephonyManager.getDataEnabled();
+ return getTelephonyManager().isDataEnabled();
}
static int getNetworkType(NetworkTemplate networkTemplate) {
@@ -250,12 +269,7 @@
}
private String getActiveSubscriberId() {
- final TelephonyManager tele = TelephonyManager.from(mContext);
- int subscriptionId = mSubscriptionId;
- if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- subscriptionId = SubscriptionManager.getDefaultDataSubscriptionId();
- }
- final String actualSubscriberId = tele.getSubscriberId(subscriptionId);
+ final String actualSubscriberId = getTelephonyManager().getSubscriberId();
return actualSubscriberId;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartDataLoader.java
index ec5a0b5..787dc55 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartDataLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartDataLoader.java
@@ -37,14 +37,14 @@
private NetworkCycleChartDataLoader(Builder builder) {
super(builder);
- mData = new ArrayList<NetworkCycleChartData>();
+ mData = new ArrayList<>();
}
@Override
void recordUsage(long start, long end) {
try {
final NetworkStats.Bucket bucket = mNetworkStatsManager.querySummaryForDevice(
- mNetworkType, mSubId, start, end);
+ mNetworkTemplate, start, end);
final long total = bucket == null ? 0L : bucket.getRxBytes() + bucket.getTxBytes();
if (total > 0L) {
final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
@@ -81,7 +81,7 @@
long usage = 0L;
try {
final NetworkStats.Bucket bucket = mNetworkStatsManager.querySummaryForDevice(
- mNetworkType, mSubId, bucketStart, bucketEnd);
+ mNetworkTemplate, bucketStart, bucketEnd);
if (bucket != null) {
usage = bucket.getRxBytes() + bucket.getTxBytes();
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
index bd9a636..43c05b8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
@@ -23,11 +23,11 @@
import android.content.Context;
import android.util.Log;
+import androidx.annotation.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.List;
-import androidx.annotation.VisibleForTesting;
-
/**
* Loader for network data usage history. It returns a list of usage data per billing cycle for the
* specific Uid(s).
@@ -44,7 +44,7 @@
super(builder);
mUids = builder.mUids;
mRetrieveDetail = builder.mRetrieveDetail;
- mData = new ArrayList<NetworkCycleDataForUid>();
+ mData = new ArrayList<>();
}
@Override
@@ -54,7 +54,7 @@
long totalForeground = 0L;
for (int uid : mUids) {
final NetworkStats stats = mNetworkStatsManager.queryDetailsForUid(
- mNetworkType, mSubId, start, end, uid);
+ mNetworkTemplate, start, end, uid);
final long usage = getTotalUsage(stats);
if (usage > 0L) {
totalUsage += usage;
@@ -100,7 +100,7 @@
private long getForegroundUsage(long start, long end, int uid) {
final NetworkStats stats = mNetworkStatsManager.queryDetailsForUidTagState(
- mNetworkType, mSubId, start, end, uid, TAG_NONE, STATE_FOREGROUND);
+ mNetworkTemplate, start, end, uid, TAG_NONE, STATE_FOREGROUND);
return getTotalUsage(stats);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
index dd6d563..3e95b01 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
@@ -49,18 +49,14 @@
public abstract class NetworkCycleDataLoader<D> extends AsyncTaskLoader<D> {
private static final String TAG = "NetworkCycleDataLoader";
protected final NetworkStatsManager mNetworkStatsManager;
- protected final String mSubId;
- protected final int mNetworkType;
+ protected final NetworkTemplate mNetworkTemplate;
private final NetworkPolicy mPolicy;
- private final NetworkTemplate mNetworkTemplate;
private final ArrayList<Long> mCycles;
@VisibleForTesting
final INetworkStatsService mNetworkStatsService;
protected NetworkCycleDataLoader(Builder<?> builder) {
super(builder.mContext);
- mSubId = builder.mSubId;
- mNetworkType = builder.mNetworkType;
mNetworkTemplate = builder.mNetworkTemplate;
mCycles = builder.mCycles;
mNetworkStatsManager = (NetworkStatsManager)
@@ -180,8 +176,6 @@
public static abstract class Builder<T extends NetworkCycleDataLoader> {
private final Context mContext;
- private String mSubId;
- private int mNetworkType;
private NetworkTemplate mNetworkTemplate;
private ArrayList<Long> mCycles;
@@ -189,14 +183,8 @@
mContext = context;
}
- public Builder<T> setSubscriberId(String subId) {
- mSubId = subId;
- return this;
- }
-
public Builder<T> setNetworkTemplate(NetworkTemplate template) {
mNetworkTemplate = template;
- mNetworkType = DataUsageController.getNetworkType(template);
return this;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsSummaryLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsSummaryLoader.java
index 34e6097..ed093629 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsSummaryLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsSummaryLoader.java
@@ -16,9 +16,10 @@
package com.android.settingslib.net;
-import android.app.usage.NetworkStatsManager;
import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
import android.content.Context;
+import android.net.NetworkTemplate;
import android.os.RemoteException;
import android.util.Log;
@@ -33,15 +34,13 @@
private final NetworkStatsManager mNetworkStatsManager;
private final long mStart;
private final long mEnd;
- private final String mSubId;
- private final int mNetworkType;
+ private final NetworkTemplate mNetworkTemplate;
private NetworkStatsSummaryLoader(Builder builder) {
super(builder.mContext);
mStart = builder.mStart;
mEnd = builder.mEnd;
- mSubId = builder.mSubId;
- mNetworkType = builder.mNetworkType;
+ mNetworkTemplate = builder.mNetworkTemplate;
mNetworkStatsManager = (NetworkStatsManager)
builder.mContext.getSystemService(Context.NETWORK_STATS_SERVICE);
}
@@ -55,7 +54,7 @@
@Override
public NetworkStats loadInBackground() {
try {
- return mNetworkStatsManager.querySummary(mNetworkType, mSubId, mStart, mEnd);
+ return mNetworkStatsManager.querySummary(mNetworkTemplate, mStart, mEnd);
} catch (RemoteException e) {
Log.e(TAG, "Exception querying network detail.", e);
return null;
@@ -78,8 +77,7 @@
private final Context mContext;
private long mStart;
private long mEnd;
- private String mSubId;
- private int mNetworkType;
+ private NetworkTemplate mNetworkTemplate;
public Builder(Context context) {
mContext = context;
@@ -95,13 +93,11 @@
return this;
}
- public Builder setSubscriberId(String subId) {
- mSubId = subId;
- return this;
- }
-
- public Builder setNetworkType(int networkType) {
- mNetworkType = networkType;
+ /**
+ * Set {@link NetworkTemplate} for builder
+ */
+ public Builder setNetworkTemplate(NetworkTemplate template) {
+ mNetworkTemplate = template;
return this;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 02bcc09..e28c612 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -179,7 +179,9 @@
public static final int SECURITY_OWE = 4;
public static final int SECURITY_SAE = 5;
public static final int SECURITY_EAP_SUITE_B = 6;
- public static final int SECURITY_MAX_VAL = 7; // Has to be the last
+ public static final int SECURITY_PSK_SAE_TRANSITION = 7;
+ public static final int SECURITY_OWE_TRANSITION = 8;
+ public static final int SECURITY_MAX_VAL = 9; // Has to be the last
private static final int PSK_UNKNOWN = 0;
private static final int PSK_WPA = 1;
@@ -782,7 +784,8 @@
ssid = bestResult.SSID;
bssid = bestResult.BSSID;
security = getSecurity(bestResult);
- if (security == SECURITY_PSK || security == SECURITY_SAE) {
+ if (security == SECURITY_PSK || security == SECURITY_SAE
+ || security == SECURITY_PSK_SAE_TRANSITION) {
pskType = getPskType(bestResult);
}
if (security == SECURITY_EAP) {
@@ -859,6 +862,7 @@
return concise ? context.getString(R.string.wifi_security_short_wep) :
context.getString(R.string.wifi_security_wep);
case SECURITY_SAE:
+ case SECURITY_PSK_SAE_TRANSITION:
if (pskType == PSK_SAE) {
return concise ? context.getString(R.string.wifi_security_short_psk_sae) :
context.getString(R.string.wifi_security_psk_sae);
@@ -866,6 +870,12 @@
return concise ? context.getString(R.string.wifi_security_short_sae) :
context.getString(R.string.wifi_security_sae);
}
+ case SECURITY_OWE_TRANSITION:
+ if (mConfig != null && getSecurity(mConfig) == SECURITY_OWE) {
+ return concise ? context.getString(R.string.wifi_security_short_owe) :
+ context.getString(R.string.wifi_security_owe);
+ }
+ return concise ? "" : context.getString(R.string.wifi_security_none);
case SECURITY_OWE:
return concise ? context.getString(R.string.wifi_security_short_owe) :
context.getString(R.string.wifi_security_owe);
@@ -1111,7 +1121,7 @@
* Return true if this AccessPoint represents a Passpoint provider configuration.
*/
public boolean isPasspointConfig() {
- return mFqdn != null;
+ return mFqdn != null && mConfig == null;
}
/**
@@ -1150,7 +1160,7 @@
if (networkId != WifiConfiguration.INVALID_NETWORK_ID) {
return networkId == info.getNetworkId();
} else if (config != null) {
- return TextUtils.equals(getKey(config), getKey());
+ return isKeyEqual(getKey(config));
} else {
// Might be an ephemeral connection with no WifiConfiguration. Try matching on SSID.
// (Note that we only do this if the WifiConfiguration explicitly equals INVALID).
@@ -1176,7 +1186,8 @@
* Can only be called for unsecured networks.
*/
public void generateOpenNetworkConfig() {
- if ((security != SECURITY_NONE) && (security != SECURITY_OWE)) {
+ if ((security != SECURITY_NONE) && (security != SECURITY_OWE)
+ && (security != SECURITY_OWE_TRANSITION)) {
throw new IllegalStateException();
}
if (mConfig != null)
@@ -1184,7 +1195,7 @@
mConfig = new WifiConfiguration();
mConfig.SSID = AccessPoint.convertToQuotedString(ssid);
- if (security == SECURITY_NONE) {
+ if (security == SECURITY_NONE || !getWifiManager().isEasyConnectSupported()) {
mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
} else {
mConfig.allowedKeyManagement.set(KeyMgmt.OWE);
@@ -1223,6 +1234,37 @@
mAccessPointListener = listener;
}
+ private static final String sPskSuffix = "," + String.valueOf(SECURITY_PSK);
+ private static final String sSaeSuffix = "," + String.valueOf(SECURITY_SAE);
+ private static final String sPskSaeSuffix = "," + String.valueOf(SECURITY_PSK_SAE_TRANSITION);
+ private static final String sOweSuffix = "," + String.valueOf(SECURITY_OWE);
+ private static final String sOpenSuffix = "," + String.valueOf(SECURITY_NONE);
+ private static final String sOweTransSuffix = "," + String.valueOf(SECURITY_OWE_TRANSITION);
+
+ private boolean isKeyEqual(String compareTo) {
+ if (mKey == null) {
+ return false;
+ }
+
+ if (compareTo.endsWith(sPskSuffix) || compareTo.endsWith(sSaeSuffix)) {
+ if (mKey.endsWith(sPskSaeSuffix)) {
+ // Special handling for PSK-SAE transition mode. If the AP has advertised both,
+ // we compare the key with both PSK and SAE for a match.
+ return TextUtils.equals(mKey.substring(0, mKey.lastIndexOf(',')),
+ compareTo.substring(0, compareTo.lastIndexOf(',')));
+ }
+ }
+ if (compareTo.endsWith(sOpenSuffix) || compareTo.endsWith(sOweSuffix)) {
+ if (mKey.endsWith(sOweTransSuffix)) {
+ // Special handling for OWE/Open networks. If AP advertises OWE in transition mode
+ // and we have an Open network saved, allow this connection to be established.
+ return TextUtils.equals(mKey.substring(0, mKey.lastIndexOf(',')),
+ compareTo.substring(0, compareTo.lastIndexOf(',')));
+ }
+ }
+ return mKey.equals(compareTo);
+ }
+
/**
* Sets {@link #mScanResults} to the given collection and updates info based on the best RSSI
* scan result.
@@ -1240,7 +1282,7 @@
if (mKey != null && !isPasspoint() && !isOsuProvider()) {
for (ScanResult result : scanResults) {
String scanResultKey = AccessPoint.getKey(result);
- if (mKey != null && !mKey.equals(scanResultKey)) {
+ if (!isKeyEqual(scanResultKey)) {
Log.d(TAG, String.format(
"ScanResult %s\nkey of %s did not match current AP key %s",
result, scanResultKey, mKey));
@@ -1546,6 +1588,8 @@
private static int getSecurity(ScanResult result) {
if (result.capabilities.contains("WEP")) {
return SECURITY_WEP;
+ } else if (result.capabilities.contains("PSK+SAE")) {
+ return SECURITY_PSK_SAE_TRANSITION;
} else if (result.capabilities.contains("SAE")) {
return SECURITY_SAE;
} else if (result.capabilities.contains("PSK")) {
@@ -1554,10 +1598,11 @@
return SECURITY_EAP_SUITE_B;
} else if (result.capabilities.contains("EAP")) {
return SECURITY_EAP;
+ } else if (result.capabilities.contains("OWE_TRANSITION")) {
+ return SECURITY_OWE_TRANSITION;
} else if (result.capabilities.contains("OWE")) {
return SECURITY_OWE;
}
-
return SECURITY_NONE;
}
@@ -1601,6 +1646,10 @@
return "SUITE_B";
} else if (security == SECURITY_OWE) {
return "OWE";
+ } else if (security == SECURITY_PSK_SAE_TRANSITION) {
+ return "PSK+SAE";
+ } else if (security == SECURITY_OWE_TRANSITION) {
+ return "OWE_TRANSITION";
}
return "NONE";
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index 6269a71..dae5464 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -201,7 +201,8 @@
return;
}
if ((mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE)
- && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE)) {
+ && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE)
+ && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE_TRANSITION)) {
mFrictionSld.setState(STATE_SECURED);
} else if (mAccessPoint.isMetered()) {
mFrictionSld.setState(STATE_METERED);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index d8172a0..3e359d2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -555,8 +555,6 @@
configsByKey.put(AccessPoint.getKey(config), config);
}
}
- ArrayMap<String, List<ScanResult>> scanResultsByApKey =
- updateScanResultCache(newScanResults);
WifiConfiguration connectionConfig = null;
if (mLastInfo != null) {
@@ -566,6 +564,9 @@
// Rather than dropping and reacquiring the lock multiple times in this method, we lock
// once for efficiency of lock acquisition time and readability
synchronized (mLock) {
+ ArrayMap<String, List<ScanResult>> scanResultsByApKey =
+ updateScanResultCache(newScanResults);
+
// Swap the current access points into a cached list for maintaining AP listeners
List<AccessPoint> cachedAccessPoints;
cachedAccessPoints = new ArrayList<>(mInternalAccessPoints);
@@ -718,6 +719,7 @@
if (accessPoint == null) {
accessPoint = new AccessPoint(mContext, config, homeScans, roamingScans);
} else {
+ accessPoint.update(config);
accessPoint.setScanResultsPasspoint(homeScans, roamingScans);
}
return accessPoint;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 683ec8b..7fac812 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -314,7 +314,8 @@
private List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>>
createPasspointMatchingWifiConfigWithScanResults(
- List<ScanResult> homeList, List<ScanResult> roamingList) {
+ List<ScanResult> homeList, List<ScanResult> roamingList,
+ String fqdn, String friendlyName) {
List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> matchingList =
new ArrayList<>();
Map<Integer, List<ScanResult>> mapping = new HashMap<>();
@@ -326,7 +327,7 @@
mapping.put(WifiManager.PASSPOINT_ROAMING_NETWORK, roamingList);
}
- matchingList.add(new Pair(buildPasspointConfiguration(FQDN_1, PROVIDER_FRIENDLY_NAME_1),
+ matchingList.add(new Pair(buildPasspointConfiguration(fqdn, friendlyName),
mapping));
return matchingList;
@@ -1077,7 +1078,7 @@
List<AccessPoint> passpointAccessPointsFirstUpdate = tracker.updatePasspointAccessPoints(
createPasspointMatchingWifiConfigWithScanResults(Arrays.asList(result),
- null), new ArrayList<>());
+ null, FQDN_1, PROVIDER_FRIENDLY_NAME_1), new ArrayList<>());
List<AccessPoint> cachedAccessPoints = new ArrayList<>(passpointAccessPointsFirstUpdate);
int prevRssi = result.level;
@@ -1086,7 +1087,7 @@
List<AccessPoint> passpointAccessPointsSecondUpdate = tracker.updatePasspointAccessPoints(
createPasspointMatchingWifiConfigWithScanResults(Arrays.asList(result),
- null), cachedAccessPoints);
+ null, FQDN_1, PROVIDER_FRIENDLY_NAME_1), cachedAccessPoints);
// Verify second update AP is the same object as the first update AP
assertThat(passpointAccessPointsFirstUpdate.get(0))
@@ -1097,6 +1098,28 @@
}
/**
+ * Verifies that the internal WifiConfiguration of a Passpoint AccessPoint is updated
+ */
+ @Test
+ public void updatePasspointAccessPoints_updatesConfig() {
+ WifiTracker tracker = createMockedWifiTracker();
+
+ ScanResult result = buildScanResult1();
+
+ List<AccessPoint> passpointAccessPoints = tracker.updatePasspointAccessPoints(
+ createPasspointMatchingWifiConfigWithScanResults(Arrays.asList(result),
+ null, FQDN_1, PROVIDER_FRIENDLY_NAME_1), new ArrayList<>());
+
+ AccessPoint ap = passpointAccessPoints.get(0);
+ assertEquals(ap.getTitle(), PROVIDER_FRIENDLY_NAME_1);
+
+ tracker.updatePasspointAccessPoints(
+ createPasspointMatchingWifiConfigWithScanResults(Arrays.asList(result),
+ null, FQDN_1, PROVIDER_FRIENDLY_NAME_2), passpointAccessPoints);
+ assertEquals(ap.getTitle(), PROVIDER_FRIENDLY_NAME_2);
+ }
+
+ /**
* Verifies that updateOsuAccessPoints will only return AccessPoints whose
* isOsuProvider() evaluates as true.
*/
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
index b27efd0..f8697a1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
@@ -191,8 +191,9 @@
shadowContext.setSystemService(Context.STORAGE_STATS_SERVICE, mStorageStatsManager);
StorageStats storageStats = new StorageStats();
storageStats.codeBytes = 10;
- storageStats.dataBytes = 20;
storageStats.cacheBytes = 30;
+ // Data bytes are a superset of cache bytes.
+ storageStats.dataBytes = storageStats.cacheBytes + 20;
when(mStorageStatsManager.queryStatsForPackage(any(UUID.class),
anyString(), any(UserHandle.class))).thenReturn(storageStats);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
index 8bd5fd2..7a553fc 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
@@ -16,8 +16,8 @@
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
-
import android.util.LongSparseLongArray;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -75,7 +75,8 @@
long[] testRequestTime = {ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO};
List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime);
- when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_OPS)).thenReturn(appOps);
+ when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_REQUEST_OPS)).thenReturn(
+ appOps);
mockTestApplicationInfos(mTestUserId, TEST_PACKAGE_NAMES);
mRecentLocationApps = new RecentLocationApps(mContext);
@@ -83,7 +84,7 @@
@Test
public void testGetAppList_shouldFilterRecentApps() {
- List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList();
+ List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(true);
// Only two of the apps have requested location within 15 min.
assertThat(requests).hasSize(2);
// Make sure apps are ordered by recency
@@ -107,11 +108,12 @@
{ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO, ONE_MIN_AGO};
List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime);
appOps.add(androidSystemPackageOps);
- when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_OPS)).thenReturn(appOps);
+ when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_REQUEST_OPS)).thenReturn(
+ appOps);
mockTestApplicationInfos(
Process.SYSTEM_UID, RecentLocationApps.ANDROID_SYSTEM_PACKAGE_NAME);
- List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList();
+ List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(true);
// Android OS shouldn't show up in the list of apps.
assertThat(requests).hasSize(2);
// Make sure apps are ordered by recency
@@ -133,7 +135,7 @@
private List<PackageOps> createTestPackageOpsList(String[] packageNameList, long[] time) {
List<PackageOps> packageOpsList = new ArrayList<>();
- for (int i = 0; i < packageNameList.length ; i++) {
+ for (int i = 0; i < packageNameList.length; i++) {
PackageOps packageOps = createPackageOps(
packageNameList[i],
TEST_UID,
@@ -156,11 +158,11 @@
private OpEntry createOpEntryWithTime(int op, long time, int duration) {
final LongSparseLongArray accessTimes = new LongSparseLongArray();
accessTimes.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP,
- AppOpsManager.OP_FLAG_SELF), time);
+ AppOpsManager.OP_FLAG_SELF), time);
final LongSparseLongArray durations = new LongSparseLongArray();
durations.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP,
- AppOpsManager.OP_FLAG_SELF), duration);
+ AppOpsManager.OP_FLAG_SELF), duration);
return new OpEntry(op, false, AppOpsManager.MODE_ALLOWED, accessTimes,
- null /*rejectTimes*/, durations, null /* proxyUids */, null /* proxyPackages */);
+ null /*rejectTimes*/, durations, null /* proxyUids */, null /* proxyPackages */);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java
index 70b04ab..030bab6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java
@@ -455,4 +455,12 @@
verify(mCallback).onConnectedDeviceChanged(PhoneMediaDevice.ID);
}
+
+ @Test
+ public void onAudioModeChanged_shouldCallOnDeviceAttributesChanged() {
+ mMediaManager.registerCallback(mCallback);
+ mMediaManager.onAudioModeChanged();
+
+ verify(mCallback).onDeviceAttributesChanged();
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
index 220463b..3da5e76 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
@@ -31,11 +31,11 @@
import android.app.usage.NetworkStats;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
-import android.net.ConnectivityManager;
import android.net.INetworkStatsSession;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.os.RemoteException;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
@@ -51,50 +51,62 @@
public class DataUsageControllerTest {
private static final String SUB_ID = "Test Subscriber";
+ private static final String SUB_ID_2 = "Test Subscriber 2";
@Mock
private INetworkStatsSession mSession;
@Mock
private TelephonyManager mTelephonyManager;
@Mock
+ private SubscriptionManager mSubscriptionManager;
+ @Mock
private NetworkStatsManager mNetworkStatsManager;
@Mock
private Context mContext;
+ private NetworkTemplate mNetworkTemplate;
+ private NetworkTemplate mNetworkTemplate2;
+ private NetworkTemplate mWifiNetworkTemplate;
private DataUsageController mController;
private NetworkStatsHistory mNetworkStatsHistory;
+ private final int mDefaultSubscriptionId = 1234;
@Before
public void setUp() throws RemoteException {
MockitoAnnotations.initMocks(this);
+ when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+ when(mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE))
+ .thenReturn(mSubscriptionManager);
when(mContext.getSystemService(NetworkStatsManager.class)).thenReturn(mNetworkStatsManager);
mController = new DataUsageController(mContext);
mNetworkStatsHistory = spy(
new NetworkStatsHistory(DateUtils.DAY_IN_MILLIS /* bucketDuration */));
doReturn(mNetworkStatsHistory)
.when(mSession).getHistoryForNetwork(any(NetworkTemplate.class), anyInt());
- final int defaultSubscriptionId = 1234;
- ShadowSubscriptionManager.setDefaultDataSubscriptionId(defaultSubscriptionId);
- doReturn(SUB_ID).when(mTelephonyManager).getSubscriberId(eq(defaultSubscriptionId));
+ ShadowSubscriptionManager.setDefaultDataSubscriptionId(mDefaultSubscriptionId);
+ doReturn(SUB_ID).when(mTelephonyManager).getSubscriberId();
+
+ mNetworkTemplate = NetworkTemplate.buildTemplateMobileAll(SUB_ID);
+ mNetworkTemplate2 = NetworkTemplate.buildTemplateMobileAll(SUB_ID_2);
+ mWifiNetworkTemplate = NetworkTemplate.buildTemplateWifiWildcard();
}
@Test
public void getHistoricalUsageLevel_shouldQuerySummaryForDevice() throws Exception {
+ mController.getHistoricalUsageLevel(mWifiNetworkTemplate);
- mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard());
-
- verify(mNetworkStatsManager).querySummaryForDevice(eq(ConnectivityManager.TYPE_WIFI),
- eq(SUB_ID), eq(0L) /* startTime */, anyLong() /* endTime */);
+ verify(mNetworkStatsManager).querySummaryForDevice(eq(mWifiNetworkTemplate),
+ eq(0L) /* startTime */, anyLong() /* endTime */);
}
@Test
public void getHistoricalUsageLevel_noUsageData_shouldReturn0() throws Exception {
- when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_WIFI),
- eq(SUB_ID), eq(0L) /* startTime */, anyLong() /* endTime */))
+ when(mNetworkStatsManager.querySummaryForDevice(eq(mWifiNetworkTemplate),
+ eq(0L) /* startTime */, anyLong() /* endTime */))
.thenReturn(mock(NetworkStats.Bucket.class));
- assertThat(mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard()))
- .isEqualTo(0L);
+ assertThat(mController.getHistoricalUsageLevel(mWifiNetworkTemplate))
+ .isEqualTo(0L);
}
@Test
@@ -104,10 +116,10 @@
final NetworkStats.Bucket bucket = mock(NetworkStats.Bucket.class);
when(bucket.getRxBytes()).thenReturn(receivedBytes);
when(bucket.getTxBytes()).thenReturn(transmittedBytes);
- when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_WIFI),
- eq(SUB_ID), eq(0L) /* startTime */, anyLong() /* endTime */)).thenReturn(bucket);
+ when(mNetworkStatsManager.querySummaryForDevice(eq(mWifiNetworkTemplate),
+ eq(0L) /* startTime */, anyLong() /* endTime */)).thenReturn(bucket);
- assertThat(mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard()))
+ assertThat(mController.getHistoricalUsageLevel(mWifiNetworkTemplate))
.isEqualTo(receivedBytes + transmittedBytes);
}
@@ -120,9 +132,8 @@
final NetworkStats.Bucket defaultSubscriberBucket = mock(NetworkStats.Bucket.class);
when(defaultSubscriberBucket.getRxBytes()).thenReturn(defaultSubRx);
when(defaultSubscriberBucket.getTxBytes()).thenReturn(defaultSubTx);
- when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_MOBILE),
- eq(SUB_ID), eq(0L)/* startTime */, anyLong() /* endTime */)).thenReturn(
- defaultSubscriberBucket);
+ when(mNetworkStatsManager.querySummaryForDevice(eq(mNetworkTemplate), eq(0L)/* startTime */,
+ anyLong() /* endTime */)).thenReturn(defaultSubscriberBucket);
// Now setup a stats bucket for a different, non-default subscription / subscriber ID.
final long nonDefaultSubRx = 7654321L;
@@ -130,19 +141,59 @@
final NetworkStats.Bucket nonDefaultSubscriberBucket = mock(NetworkStats.Bucket.class);
when(nonDefaultSubscriberBucket.getRxBytes()).thenReturn(nonDefaultSubRx);
when(nonDefaultSubscriberBucket.getTxBytes()).thenReturn(nonDefaultSubTx);
- final int explictSubscriptionId = 55;
- final String subscriberId2 = "Test Subscriber 2";
- when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_MOBILE),
- eq(subscriberId2), eq(0L)/* startTime */, anyLong() /* endTime */)).thenReturn(
+ final int explicitSubscriptionId = 55;
+ when(mNetworkStatsManager.querySummaryForDevice(eq(mNetworkTemplate2),
+ eq(0L)/* startTime */, anyLong() /* endTime */)).thenReturn(
nonDefaultSubscriberBucket);
- doReturn(subscriberId2).when(mTelephonyManager).getSubscriberId(explictSubscriptionId);
+ doReturn(SUB_ID_2).when(mTelephonyManager).getSubscriberId();
// Now verify that when we're asking for stats on the non-default subscription, we get
// the data back for that subscription and *not* the default one.
- mController.setSubscriptionId(explictSubscriptionId);
+ mController.setSubscriptionId(explicitSubscriptionId);
- assertThat(mController.getHistoricalUsageLevel(
- NetworkTemplate.buildTemplateMobileAll(subscriberId2))).isEqualTo(
+ assertThat(mController.getHistoricalUsageLevel(mNetworkTemplate2)).isEqualTo(
nonDefaultSubRx + nonDefaultSubTx);
}
+
+ @Test
+ public void getTelephonyManager_shouldCreateWithExplicitSubId() {
+ int explicitSubId = 1;
+ TelephonyManager tmForSub1 = new TelephonyManager(mContext, explicitSubId);
+ when(mTelephonyManager.createForSubscriptionId(eq(explicitSubId))).thenReturn(tmForSub1);
+
+ // Set a specific subId.
+ mController.setSubscriptionId(explicitSubId);
+
+ assertThat(mController.getTelephonyManager()).isEqualTo(tmForSub1);
+ verify(mTelephonyManager).createForSubscriptionId(eq(explicitSubId));
+ }
+
+ @Test
+ public void getTelephonyManager_noExplicitSubId_shouldCreateWithDefaultDataSubId()
+ throws Exception {
+ TelephonyManager tmForDefaultSub = new TelephonyManager(mContext, mDefaultSubscriptionId);
+ when(mTelephonyManager.createForSubscriptionId(mDefaultSubscriptionId))
+ .thenReturn(tmForDefaultSub);
+
+ // No subId is set. It should use default data sub.
+ assertThat(mController.getTelephonyManager()).isEqualTo(tmForDefaultSub);
+ verify(mTelephonyManager).createForSubscriptionId(mDefaultSubscriptionId);
+ }
+
+ @Test
+ public void getTelephonyManager_noExplicitSubIdOrDefaultSub_shouldCreateWithActiveSub()
+ throws Exception {
+ int activeSubId = 2;
+ ShadowSubscriptionManager.setDefaultDataSubscriptionId(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ when(mSubscriptionManager.getActiveSubscriptionIdList())
+ .thenReturn(new int[] {activeSubId});
+ TelephonyManager tmForActiveSub = new TelephonyManager(mContext, activeSubId);
+ when(mTelephonyManager.createForSubscriptionId(activeSubId))
+ .thenReturn(tmForActiveSub);
+
+ // No subId is set, default data subId is also not set. So should use the only active subId.
+ assertThat(mController.getTelephonyManager()).isEqualTo(tmForActiveSub);
+ verify(mTelephonyManager).createForSubscriptionId(activeSubId);
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java
index 011f234..c3e1613 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java
@@ -21,9 +21,9 @@
import android.app.usage.NetworkStatsManager;
import android.content.Context;
-import android.net.ConnectivityManager;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
+import android.net.NetworkTemplate;
import android.os.RemoteException;
import android.text.format.DateUtils;
@@ -43,6 +43,8 @@
private NetworkPolicyManager mNetworkPolicyManager;
@Mock
private Context mContext;
+ @Mock
+ private NetworkTemplate mNetworkTemplate;
private NetworkCycleChartDataLoader mLoader;
@@ -60,13 +62,12 @@
public void recordUsage_shouldQueryNetworkSummaryForDevice() throws RemoteException {
final long end = System.currentTimeMillis();
final long start = end - (DateUtils.WEEK_IN_MILLIS * 4);
- final int networkType = ConnectivityManager.TYPE_MOBILE;
- final String subId = "TestSubscriber";
mLoader = NetworkCycleChartDataLoader.builder(mContext)
- .setSubscriberId(subId).build();
+ .setNetworkTemplate(mNetworkTemplate)
+ .build();
mLoader.recordUsage(start, end);
- verify(mNetworkStatsManager).querySummaryForDevice(networkType, subId, start, end);
+ verify(mNetworkStatsManager).querySummaryForDevice(mNetworkTemplate, start, end);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
index aafb46a..877eb61 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
@@ -28,9 +28,9 @@
import android.app.usage.NetworkStatsManager;
import android.content.Context;
-import android.net.ConnectivityManager;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
+import android.net.NetworkTemplate;
import android.text.format.DateUtils;
import org.junit.Before;
@@ -42,6 +42,7 @@
@RunWith(RobolectricTestRunner.class)
public class NetworkCycleDataForUidLoaderTest {
+ private static final String SUB_ID = "Test Subscriber";
@Mock
private NetworkStatsManager mNetworkStatsManager;
@@ -49,6 +50,7 @@
private NetworkPolicyManager mNetworkPolicyManager;
@Mock
private Context mContext;
+ private NetworkTemplate mNetworkTemplate;
private NetworkCycleDataForUidLoader mLoader;
@@ -56,64 +58,62 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(Context.NETWORK_STATS_SERVICE))
- .thenReturn(mNetworkStatsManager);
+ .thenReturn(mNetworkStatsManager);
when(mContext.getSystemService(Context.NETWORK_POLICY_SERVICE))
- .thenReturn(mNetworkPolicyManager);
+ .thenReturn(mNetworkPolicyManager);
when(mNetworkPolicyManager.getNetworkPolicies()).thenReturn(new NetworkPolicy[0]);
+ mNetworkTemplate = NetworkTemplate.buildTemplateMobileAll(SUB_ID);
}
@Test
public void recordUsage_shouldQueryNetworkDetailsForUidAndForegroundState() {
final long end = System.currentTimeMillis();
final long start = end - (DateUtils.WEEK_IN_MILLIS * 4);
- final int networkType = ConnectivityManager.TYPE_MOBILE;
- final String subId = "TestSubscriber";
final int uid = 1;
mLoader = spy(NetworkCycleDataForUidLoader.builder(mContext)
- .addUid(uid).setSubscriberId(subId).build());
+ .addUid(uid)
+ .setNetworkTemplate(mNetworkTemplate)
+ .build());
doReturn(1024L).when(mLoader).getTotalUsage(any());
mLoader.recordUsage(start, end);
- verify(mNetworkStatsManager).queryDetailsForUid(networkType, subId, start, end, uid);
+ verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, uid);
verify(mNetworkStatsManager).queryDetailsForUidTagState(
- networkType, subId, start, end, uid, TAG_NONE, STATE_FOREGROUND);
+ mNetworkTemplate, start, end, uid, TAG_NONE, STATE_FOREGROUND);
}
@Test
public void recordUsage_retrieveDetailIsFalse_shouldNotQueryNetworkForegroundState() {
final long end = System.currentTimeMillis();
final long start = end - (DateUtils.WEEK_IN_MILLIS * 4);
- final int networkType = ConnectivityManager.TYPE_MOBILE;
- final String subId = "TestSubscriber";
final int uid = 1;
mLoader = spy(NetworkCycleDataForUidLoader.builder(mContext)
- .setRetrieveDetail(false).addUid(uid).setSubscriberId(subId).build());
+ .setRetrieveDetail(false).addUid(uid).build());
doReturn(1024L).when(mLoader).getTotalUsage(any());
mLoader.recordUsage(start, end);
verify(mNetworkStatsManager, never()).queryDetailsForUidTagState(
- networkType, subId, start, end, uid, TAG_NONE, STATE_FOREGROUND);
+ mNetworkTemplate, start, end, uid, TAG_NONE, STATE_FOREGROUND);
}
@Test
public void recordUsage_multipleUids_shouldQueryNetworkDetailsForEachUid() {
final long end = System.currentTimeMillis();
final long start = end - (DateUtils.WEEK_IN_MILLIS * 4);
- final int networkType = ConnectivityManager.TYPE_MOBILE;
- final String subId = "TestSubscriber";
mLoader = spy(NetworkCycleDataForUidLoader.builder(mContext)
- .addUid(1)
- .addUid(2)
- .addUid(3)
- .setSubscriberId(subId).build());
+ .addUid(1)
+ .addUid(2)
+ .addUid(3)
+ .setNetworkTemplate(mNetworkTemplate)
+ .build());
doReturn(1024L).when(mLoader).getTotalUsage(any());
mLoader.recordUsage(start, end);
- verify(mNetworkStatsManager).queryDetailsForUid(networkType, subId, start, end, 1);
- verify(mNetworkStatsManager).queryDetailsForUid(networkType, subId, start, end, 2);
- verify(mNetworkStatsManager).queryDetailsForUid(networkType, subId, start, end, 3);
+ verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 1);
+ verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 2);
+ verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 3);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
index c5f54bb..74b9151 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
@@ -126,8 +126,6 @@
when(mIterator.next()).thenReturn(cycle);
mLoader = spy(new NetworkCycleDataTestLoader(mContext));
ReflectionHelpers.setField(mLoader, "mPolicy", mPolicy);
- ReflectionHelpers.setField(mLoader, "mNetworkType", networkType);
- ReflectionHelpers.setField(mLoader, "mSubId", subId);
mLoader.loadPolicyData();
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index d420966..dd72d57 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -65,19 +65,19 @@
<!-- user interface sound effects -->
<integer name="def_power_sounds_enabled">1</integer>
- <string name="def_low_battery_sound" translatable="false">/system/media/audio/ui/LowBattery.ogg</string>
+ <string name="def_low_battery_sound" translatable="false">/product/media/audio/ui/LowBattery.ogg</string>
<integer name="def_dock_sounds_enabled">0</integer>
<integer name="def_dock_sounds_enabled_when_accessibility">0</integer>
- <string name="def_desk_dock_sound" translatable="false">/system/media/audio/ui/Dock.ogg</string>
- <string name="def_desk_undock_sound" translatable="false">/system/media/audio/ui/Undock.ogg</string>
- <string name="def_car_dock_sound" translatable="false">/system/media/audio/ui/Dock.ogg</string>
- <string name="def_car_undock_sound" translatable="false">/system/media/audio/ui/Undock.ogg</string>
+ <string name="def_desk_dock_sound" translatable="false">/product/media/audio/ui/Dock.ogg</string>
+ <string name="def_desk_undock_sound" translatable="false">/product/media/audio/ui/Undock.ogg</string>
+ <string name="def_car_dock_sound" translatable="false">/product/media/audio/ui/Dock.ogg</string>
+ <string name="def_car_undock_sound" translatable="false">/product/media/audio/ui/Undock.ogg</string>
<integer name="def_lockscreen_sounds_enabled">1</integer>
- <string name="def_lock_sound" translatable="false">/system/media/audio/ui/Lock.ogg</string>
- <string name="def_unlock_sound" translatable="false">/system/media/audio/ui/Unlock.ogg</string>
- <string name="def_trusted_sound" translatable="false">/system/media/audio/ui/Trusted.ogg</string>
- <string name="def_wireless_charging_started_sound" translatable="false">/system/media/audio/ui/WirelessChargingStarted.ogg</string>
- <string name="def_charging_started_sound" translatable="false">/system/media/audio/ui/ChargingStarted.ogg</string>
+ <string name="def_lock_sound" translatable="false">/product/media/audio/ui/Lock.ogg</string>
+ <string name="def_unlock_sound" translatable="false">/product/media/audio/ui/Unlock.ogg</string>
+ <string name="def_trusted_sound" translatable="false">/product/media/audio/ui/Trusted.ogg</string>
+ <string name="def_wireless_charging_started_sound" translatable="false">/product/media/audio/ui/WirelessChargingStarted.ogg</string>
+ <string name="def_charging_started_sound" translatable="false">/product/media/audio/ui/ChargingStarted.ogg</string>
<!-- sound trigger detection service default values -->
<integer name="def_max_sound_trigger_detection_service_ops_per_day" translatable="false">1000</integer>
@@ -225,8 +225,14 @@
<bool name="def_charging_sounds_enabled">true</bool>
<!-- Default for Settings.Secure.NOTIFICATION_BUBBLES -->
- <bool name="def_notification_bubbles">true</bool>
+ <bool name="def_notification_bubbles">false</bool>
<!-- Default for Settings.Secure.AWARE_ENABLED -->
<bool name="def_aware_enabled">false</bool>
+
+ <!-- Default for Settings.Secure.SKIP_GESTURE -->
+ <bool name="def_skip_gesture">false</bool>
+
+ <!-- Default for Settings.Secure.SILENCE_GESTURE -->
+ <bool name="def_silence_gesture">false</bool>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 2f3a42f..6558c87a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3237,7 +3237,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 178;
+ private static final int SETTINGS_VERSION = 180;
private final int mUserId;
@@ -4356,6 +4356,50 @@
currentVersion = 178;
}
+ if (currentVersion == 178) {
+ // Version 178: Set the default value for Secure Settings:
+ // SKIP_GESTURE & SILENCE_GESTURE
+
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+
+ final Setting skipGesture = secureSettings.getSettingLocked(
+ Secure.SKIP_GESTURE);
+
+ if (skipGesture.isNull()) {
+ final boolean defSkipGesture = getContext().getResources().getBoolean(
+ R.bool.def_skip_gesture);
+ secureSettings.insertSettingLocked(
+ Secure.SKIP_GESTURE, defSkipGesture ? "1" : "0",
+ null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+
+ final Setting silenceGesture = secureSettings.getSettingLocked(
+ Secure.SILENCE_GESTURE);
+
+ if (silenceGesture.isNull()) {
+ final boolean defSilenceGesture = getContext().getResources().getBoolean(
+ R.bool.def_silence_gesture);
+ secureSettings.insertSettingLocked(
+ Secure.SILENCE_GESTURE, defSilenceGesture ? "1" : "0",
+ null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+
+ currentVersion = 179;
+ }
+
+ if (currentVersion == 179) {
+ // Version 178: Reset the default for Secure Settings: NOTIFICATION_BUBBLES
+ // This is originally set in version 173, however, the default value changed
+ // so this step is to ensure the value is updated to the correct defaulte
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+
+ secureSettings.insertSettingLocked(Secure.NOTIFICATION_BUBBLES,
+ getContext().getResources().getBoolean(
+ R.bool.def_notification_bubbles) ? "1" : "0", null,
+ true, SettingsState.SYSTEM_PACKAGE_NAME);
+
+ currentVersion = 180;
+ }
// vXXX: Add new settings above this point.
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 314b74a..16fce89 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -152,6 +152,7 @@
<uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
<uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
+ <uses-permission android:name="android.permission.STATUS_BAR" />
<!-- Permission needed to rename bugreport notifications (so they're not shown as Shell) -->
<uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
<uses-permission android:name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" />
diff --git a/packages/Shell/res/values-pa/strings.xml b/packages/Shell/res/values-pa/strings.xml
index cdf3769..8894814 100644
--- a/packages/Shell/res/values-pa/strings.xml
+++ b/packages/Shell/res/values-pa/strings.xml
@@ -35,7 +35,7 @@
<string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"ਬੱਗ ਰਿਪੋਰਟ ਵੇਰਵਿਆਂ ਨੂੰ ਜ਼ਿਪ ਫ਼ਾਈਲ ਵਿੱਚ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
<string name="bugreport_unnamed" msgid="2800582406842092709">"ਬਿਨਾਂ-ਨਾਮ"</string>
<string name="bugreport_info_action" msgid="2158204228510576227">"ਵੇਰਵੇ"</string>
- <string name="bugreport_screenshot_action" msgid="8677781721940614995">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਵੋ"</string>
<string name="bugreport_screenshot_taken" msgid="5684211273096253120">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸਫਲਤਾਪੂਰਵਕ ਲਿਆ ਗਿਆ।"</string>
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਨਹੀਂ ਲਿਆ ਜਾ ਸਕਿਆ।"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਵੇਰਵੇ"</string>
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index c2495b5..9425941 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -58,6 +58,7 @@
"androidx.arch.core_core-runtime",
"androidx.lifecycle_lifecycle-extensions",
"androidx.dynamicanimation_dynamicanimation",
+ "iconloader_base",
"SystemUI-tags",
"SystemUI-proto",
"dagger2-2.19",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 02d826f..4b4912c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -444,7 +444,7 @@
<activity
android:name=".media.MediaProjectionPermissionActivity"
android:exported="true"
- android:theme="@style/Theme.MediaProjectionAlertDialog"
+ android:theme="@style/Theme.SystemUI.MediaProjectionAlertDialog"
android:finishOnCloseSystemDialogs="true"
android:launchMode="singleTop"
android:excludeFromRecents="true"
diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java
index b7bb751..a150de9 100644
--- a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java
@@ -662,11 +662,17 @@
public final void onBusEvent(ExpandPipEvent event) {
PipUI pipUi = getComponent(PipUI.class);
+ if (pipUi == null) {
+ return;
+ }
pipUi.expandPip();
}
public final void onBusEvent(HidePipMenuEvent event) {
PipUI pipUi = getComponent(PipUI.class);
+ if (pipUi == null) {
+ return;
+ }
event.getAnimationTrigger().increment();
pipUi.hidePipMenu(() -> {
event.getAnimationTrigger().increment();
diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 7c6a76f..2df79d8 100644
--- a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -113,7 +113,7 @@
: t.realActivity;
final int windowingMode = t.configuration.windowConfiguration.getWindowingMode();
TaskKey taskKey = new TaskKey(t.persistentId, windowingMode, t.baseIntent,
- sourceComponent, t.userId, t.lastActiveTime);
+ sourceComponent, t.userId, t.lastActiveTime, t.displayId);
boolean isFreeformTask = windowingMode == WINDOWING_MODE_FREEFORM;
boolean isStackTask = !isFreeformTask;
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
new file mode 100644
index 0000000..28d5402
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.plugins;
+
+import android.net.Uri;
+import android.view.MotionEvent;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+import java.io.PrintWriter;
+
+/**
+ * Interface that decides whether a touch on the phone was accidental. i.e. Pocket Dialing.
+ *
+ * {@see com.android.systemui.classifier.FalsingManagerImpl}
+ */
+@ProvidesInterface(version = FalsingManager.VERSION)
+public interface FalsingManager {
+ int VERSION = 1;
+
+ void onSucccessfulUnlock();
+
+ void onNotificationActive();
+
+ void setShowingAod(boolean showingAod);
+
+ void onNotificatonStartDraggingDown();
+
+ boolean isUnlockingDisabled();
+
+ boolean isFalseTouch();
+
+ void onNotificatonStopDraggingDown();
+
+ void setNotificationExpanded();
+
+ boolean isClassiferEnabled();
+
+ void onQsDown();
+
+ void setQsExpanded(boolean expanded);
+
+ boolean shouldEnforceBouncer();
+
+ void onTrackingStarted(boolean secure);
+
+ void onTrackingStopped();
+
+ void onLeftAffordanceOn();
+
+ void onCameraOn();
+
+ void onAffordanceSwipingStarted(boolean rightCorner);
+
+ void onAffordanceSwipingAborted();
+
+ void onStartExpandingFromPulse();
+
+ void onExpansionFromPulseStopped();
+
+ Uri reportRejectedTouch();
+
+ void onScreenOnFromTouch();
+
+ boolean isReportingEnabled();
+
+ void onUnlockHintStarted();
+
+ void onCameraHintStarted();
+
+ void onLeftAffordanceHintStarted();
+
+ void onScreenTurningOn();
+
+ void onScreenOff();
+
+ void onNotificatonStopDismissing();
+
+ void onNotificationDismissed();
+
+ void onNotificatonStartDismissing();
+
+ void onNotificationDoubleTap(boolean accepted, float dx, float dy);
+
+ void onBouncerShown();
+
+ void onBouncerHidden();
+
+ void onTouchEvent(MotionEvent ev, int width, int height);
+
+ void dump(PrintWriter pw);
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingPlugin.java
index dce02e1..53d708d 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingPlugin.java
@@ -16,18 +16,22 @@
package com.android.systemui.plugins;
+import android.content.Context;
+
+import com.android.systemui.plugins.annotations.DependsOn;
import com.android.systemui.plugins.annotations.ProvidesInterface;
/**
* Used to capture Falsing data (related to unlocking the screen).
*
* The intent is that the data can later be analyzed to validate the quality of the
- * {@link com.android.systemui.classifier.FalsingManager}.
+ * {@link FalsingManager}.
*/
@ProvidesInterface(action = FalsingPlugin.ACTION, version = FalsingPlugin.VERSION)
+@DependsOn(target = FalsingManager.class)
public interface FalsingPlugin extends Plugin {
String ACTION = "com.android.systemui.action.FALSING_PLUGIN";
- int VERSION = 1;
+ int VERSION = 2;
/**
* Called when there is data to be recorded.
@@ -35,5 +39,14 @@
* @param success Indicates whether the action is considered a success.
* @param data The raw data to be recorded for analysis.
*/
- void dataCollected(boolean success, byte[] data);
+ default void dataCollected(boolean success, byte[] data) { }
+
+ /**
+ * Return a {@link FalsingManager} to be used in place of the system's default.
+ *
+ * @param context
+ */
+ default FalsingManager getFalsingManager(Context context) {
+ return null;
+ }
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java
index 68d2ed7..d0694ab 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java
@@ -16,7 +16,9 @@
package com.android.systemui.plugins;
+import android.annotation.Nullable;
import android.app.PendingIntent;
+import android.graphics.drawable.Drawable;
import android.view.View;
import com.android.systemui.plugins.annotations.DependsOn;
@@ -98,5 +100,13 @@
* Invoked when the device is either locked or unlocked.
*/
void onDeviceLockStateChanged(boolean locked);
+
+ /**
+ * Optionally returns a drawable to be used as the background for Global Actions.
+ */
+ @Nullable
+ default Drawable getBackgroundDrawable() {
+ return null;
+ }
}
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java
index 61aa60b..90fc86b 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java
@@ -13,18 +13,28 @@
*/
package com.android.systemui.plugins;
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
import android.view.View;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
@ProvidesInterface(action = OverlayPlugin.ACTION, version = OverlayPlugin.VERSION)
public interface OverlayPlugin extends Plugin {
String ACTION = "com.android.systemui.action.PLUGIN_OVERLAY";
- int VERSION = 2;
+ int VERSION = 3;
+ /**
+ * Setup overlay plugin
+ */
void setup(View statusBar, View navBar);
+ /**
+ * Setup overlay plugin with callback
+ */
+ default void setup(View statusBar, View navBar, Callback callback) {
+ setup(statusBar, navBar);
+ }
+
default boolean holdStatusBarOpen() {
return false;
}
@@ -34,4 +44,11 @@
*/
default void setCollapseDesired(boolean collapseDesired) {
}
+
+ /**
+ * Used to update system ui whether to hold status bar open
+ */
+ interface Callback {
+ void onHoldStatusBarOpenChange();
+ }
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
deleted file mode 100644
index e25930c..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.plugins.statusbar.phone;
-
-import android.annotation.Nullable;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.systemui.plugins.Plugin;
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
-@ProvidesInterface(action = NavBarButtonProvider.ACTION, version = NavBarButtonProvider.VERSION)
-public interface NavBarButtonProvider extends Plugin {
-
- public static final String ACTION = "com.android.systemui.action.PLUGIN_NAV_BUTTON";
-
- public static final int VERSION = 2;
-
- /**
- * Returns a view in the nav bar. If the id is set "back", "home", "recent_apps", "menu",
- * or "ime_switcher", it is expected to implement ButtonInterface.
- */
- public View createView(String spec, ViewGroup parent);
-
- /**
- * Interface for button actions.
- */
- interface ButtonInterface {
-
- void setImageDrawable(@Nullable Drawable drawable);
-
- void abortCurrentGesture();
-
- void setVertical(boolean vertical);
-
- default void setCarMode(boolean carMode) {
- }
-
- void setDarkIntensity(float intensity);
-
- void setDelayTouchFeedback(boolean shouldDelay);
- }
-}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
deleted file mode 100644
index 99cc3a3..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.plugins.statusbar.phone;
-
-import android.graphics.Canvas;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.systemui.plugins.Plugin;
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-import java.io.PrintWriter;
-
-@ProvidesInterface(action = NavGesture.ACTION, version = NavGesture.VERSION)
-public interface NavGesture extends Plugin {
-
- public static final String ACTION = "com.android.systemui.action.PLUGIN_NAV_GESTURE";
-
- public static final int VERSION = 1;
-
- public GestureHelper getGestureHelper();
-
- public interface GestureHelper {
- public boolean onTouchEvent(MotionEvent event);
-
- public boolean onInterceptTouchEvent(MotionEvent event);
-
- public void setBarState(boolean isRtl, int navBarPosition);
-
- public void onDraw(Canvas canvas);
-
- public void onDarkIntensityChange(float intensity);
-
- public void onLayout(boolean changed, int left, int top, int right, int bottom);
-
- public void onNavigationButtonLongPress(View v);
-
- public default void destroy() { }
-
- public default void dump(PrintWriter pw) { }
- }
-
-}
diff --git a/packages/SystemUI/res-keyguard/drawable/analog_frame.xml b/packages/SystemUI/res-keyguard/drawable/analog_frame.xml
index a663ac8..3196169 100644
--- a/packages/SystemUI/res-keyguard/drawable/analog_frame.xml
+++ b/packages/SystemUI/res-keyguard/drawable/analog_frame.xml
@@ -1,7 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="250dp"
- android:width="250dp"
+ android:height="380dp"
+ android:width="380dp"
android:viewportHeight="380"
android:viewportWidth="380">
- <path android:fillColor="#000000" android:pathData="M190,190m0,2a2,2 0,1 1,0 -4a2,2 0,1 1,0 4"/>
+ <path android:fillColor="#000000" android:pathData="M190,190m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
</vector>
diff --git a/packages/SystemUI/res-keyguard/drawable/analog_hour_hand.xml b/packages/SystemUI/res-keyguard/drawable/analog_hour_hand.xml
index c7b6d60..a05b16a 100644
--- a/packages/SystemUI/res-keyguard/drawable/analog_hour_hand.xml
+++ b/packages/SystemUI/res-keyguard/drawable/analog_hour_hand.xml
@@ -1,7 +1,4 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="250dp"
- android:width="250dp"
- android:viewportHeight="380"
- android:viewportWidth="380">
- <path android:fillColor="#777777" android:fillType="evenOdd" android:pathData="M203,190C203,185.398 200.608,181.354 197,179.044L197,58C197,54.134 193.866,51 190,51C186.134,51 183,54.134 183,58L183,179.043C179.392,181.354 177,185.397 177,190C177,197.18 182.82,203 190,203C197.18,203 203,197.18 203,190Z"/>
+<vector android:height="380dp" android:viewportHeight="380"
+ android:viewportWidth="380" android:width="380dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#777777" android:fillType="evenOdd" android:pathData="m200,190.047c0.018,-3.701 -1.978,-6.942 -4.959,-8.686l0.582,-123.337c0.013,-2.761 -2.215,-5.011 -4.976,-5.024 -2.761,-0.013 -5.01,2.215 -5.024,4.976L185.041,181.314c-2.997,1.715 -5.024,4.937 -5.041,8.639 -0.026,5.523 4.43,10.021 9.953,10.047 5.523,0.026 10.021,-4.43 10.047,-9.953z"/>
</vector>
diff --git a/packages/SystemUI/res-keyguard/drawable/analog_minute_hand.xml b/packages/SystemUI/res-keyguard/drawable/analog_minute_hand.xml
index 458275b..1277b62 100644
--- a/packages/SystemUI/res-keyguard/drawable/analog_minute_hand.xml
+++ b/packages/SystemUI/res-keyguard/drawable/analog_minute_hand.xml
@@ -1,7 +1,4 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="250dp"
- android:width="250dp"
- android:viewportHeight="380"
- android:viewportWidth="380">
- <path android:fillColor="#FFFFFF" android:pathData="M192,182.252C195.45,183.14 198,186.272 198,190C198,194.418 194.418,198 190,198C185.582,198 182,194.418 182,190C182,186.272 184.55,183.14 188,182.252L188,10C188,8.895 188.895,8 190,8C191.105,8 192,8.895 192,10L192,182.252Z"/>
+<vector android:height="380dp" android:viewportHeight="380"
+ android:viewportWidth="380" android:width="380dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#aaaaaa" android:fillType="evenOdd" android:pathData="m191,184.083c2.838,0.476 5,2.944 5,5.917 0,3.314 -2.686,6 -6,6 -3.314,0 -6,-2.686 -6,-6 0,-2.973 2.162,-5.441 5,-5.917V9c0,-0.552 0.448,-1 1,-1 0.552,0 1,0.448 1,1z"/>
</vector>
diff --git a/packages/SystemUI/res-keyguard/layout/digital_clock.xml b/packages/SystemUI/res-keyguard/layout/digital_clock.xml
index e88e2c9..38ee081 100644
--- a/packages/SystemUI/res-keyguard/layout/digital_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/digital_clock.xml
@@ -20,9 +20,20 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true">
- <include
+ <TextClock
android:id="@+id/lock_screen_clock"
- layout="@layout/text_clock"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:gravity="center_horizontal"
+ android:paddingBottom="@dimen/widget_vertical_padding_clock"
+ android:letterSpacing="0.03"
+ android:textColor="?attr/wallpaperTextColor"
+ android:singleLine="true"
+ style="@style/widget_small_bold"
+ android:format12Hour="@string/keyguard_widget_12_hours_format"
+ android:format24Hour="@string/keyguard_widget_24_hours_format"
+ android:elegantTextHeight="false"
/>
</FrameLayout>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
index 8c80e78..7986809 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
@@ -19,8 +19,7 @@
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:clipChildren="false"
- android:clipToPadding="false"
- android:fitsSystemWindows="true">
+ android:clipToPadding="false">
<include
style="@style/BouncerSecurityContainer"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 86ed9e3..bf2963c 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -30,23 +30,35 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true">
- <include
- android:id="@+id/default_clock_view"
- layout="@layout/text_clock" />
<TextClock
- android:id="@+id/default_clock_view_bold"
+ android:id="@+id/default_clock_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
- android:letterSpacing="0.03"
+ android:paddingBottom="@dimen/title_clock_padding"
+ android:letterSpacing="0.02"
android:textColor="?attr/wallpaperTextColor"
android:singleLine="true"
- style="@style/widget_big_bold"
+ style="@style/widget_big"
android:format12Hour="@string/keyguard_widget_12_hours_format"
android:format24Hour="@string/keyguard_widget_24_hours_format"
android:elegantTextHeight="false"
- android:visibility="gone"
+ />
+ <TextClock
+ android:id="@+id/default_clock_view_bold"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|center_horizontal"
+ android:gravity="center_horizontal"
+ android:letterSpacing="0.03"
+ android:textColor="?attr/wallpaperTextColor"
+ android:singleLine="true"
+ style="@style/widget_title_bold"
+ android:format12Hour="@string/keyguard_widget_12_hours_format"
+ android:format24Hour="@string/keyguard_widget_24_hours_format"
+ android:elegantTextHeight="false"
+ android:visibility="invisible"
/>
</FrameLayout>
<include layout="@layout/keyguard_status_area"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
index 29376ce0..796123d 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
@@ -38,6 +38,7 @@
android:clipChildren="false"
android:clipToPadding="false"
android:padding="0dp"
+ android:fitsSystemWindows="true"
android:layout_gravity="center">
<com.android.keyguard.KeyguardSecurityViewFlipper
android:id="@+id/view_flipper"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index dc45b4b..a84ddaf 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -32,8 +32,9 @@
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingStart="64dp"
- android:paddingEnd="64dp"
+ android:paddingStart="44dp"
+ android:paddingEnd="44dp"
+ android:letterSpacing="0.02"
android:visibility="gone"
android:textColor="?attr/wallpaperTextColor"
android:theme="@style/TextAppearance.Keyguard"
@@ -45,4 +46,4 @@
android:orientation="horizontal"
android:gravity="center"
/>
-</com.android.keyguard.KeyguardSliceView>
\ No newline at end of file
+</com.android.keyguard.KeyguardSliceView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index 10fea9d..04d6afc 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -29,6 +29,7 @@
androidprv:layout_maxHeight="@dimen/keyguard_security_height"
android:gravity="center_horizontal|top">
<LinearLayout
+ android:id="@+id/status_view_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/widget_vertical_padding"
diff --git a/packages/SystemUI/res-keyguard/layout/text_clock.xml b/packages/SystemUI/res-keyguard/layout/text_clock.xml
deleted file mode 100644
index 9f7ea0d..0000000
--- a/packages/SystemUI/res-keyguard/layout/text_clock.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2019 The Android Open 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.
- -->
-<TextClock
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:gravity="center_horizontal"
- android:letterSpacing="0.03"
- android:textColor="?attr/wallpaperTextColor"
- android:singleLine="true"
- style="@style/widget_big"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format"
- android:elegantTextHeight="false"
-/>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index 07142b0..bb48226 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -41,9 +41,9 @@
<string name="keyguard_low_battery" msgid="9218432555787624490">"Connecta el carregador."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"Prem Menú per desbloquejar."</string>
<string name="keyguard_network_locked_message" msgid="6743537524631420759">"La xarxa està bloquejada"</string>
- <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"No hi ha cap targeta SIM"</string>
- <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"No hi ha cap targeta SIM a la tauleta."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"No hi ha cap targeta SIM al telèfon."</string>
+ <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"No hi ha cap SIM"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"No hi ha cap SIM a la tauleta."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"No hi ha cap SIM al telèfon."</string>
<string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Insereix una targeta SIM."</string>
<string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"Falta la targeta SIM o no es pot llegir. Insereix-ne una."</string>
<string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"La targeta SIM no es pot fer servir."</string>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index 5668576..e60930d 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -100,8 +100,8 @@
<string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"Du har forsøgt at låse telefonen op med den forkerte adgangskode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg fjernes arbejdsprofilen, hvilket sletter alle profildata."</string>
<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"Du har forsøgt at låse denne tablet op på forkert vis <xliff:g id="NUMBER">%d</xliff:g> gange. Arbejdsprofilen fjernes, hvilket sletter alle profildata."</string>
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"Du har forsøgt at låse telefonen op på forkert vis <xliff:g id="NUMBER">%d</xliff:g> gange. Arbejdsprofilen fjernes, hvilket sletter alle profildata."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din tablet op ved hjælp af en e-mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din telefon op ved hjælp af en e-mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din tablet op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din telefon op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"Forkert pinkode til SIM-kort. Du er nu nødt til at kontakte dit mobilselskab for at låse din enhed op."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
<item quantity="one">Forkert pinkode til SIM-kort. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøg tilbage.</item>
diff --git a/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml b/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
index 3fb86d0..669f8fb 100644
--- a/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
@@ -16,5 +16,5 @@
-->
<resources>
- <dimen name="widget_big_font_size">64dp</dimen>
-</resources>
\ No newline at end of file
+ <dimen name="widget_big_font_size">54dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml b/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
index 3fb86d0..669f8fb 100644
--- a/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
@@ -16,5 +16,5 @@
-->
<resources>
- <dimen name="widget_big_font_size">64dp</dimen>
-</resources>
\ No newline at end of file
+ <dimen name="widget_big_font_size">54dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index 6504910..86e14dc 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -96,10 +96,10 @@
<string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"आपने फ़ोन का लॉक खोलने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत कोशिश करने पर, इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा मिट जाएगा."</string>
<string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"आपने टैबलेट का लॉक खोलने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा हट जाएगा."</string>
<string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"आपने फ़ोन का लॉक खोलने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा हट जाएगा."</string>
- <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल कोशिशों के बाद, कार्य प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string>
- <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल कोशिशों के बाद, कार्य प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. कार्य प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. कार्य प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल कोशिशों के बाद, वर्क प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल कोशिशों के बाद, वर्क प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. वर्क प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. वर्क प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"आपने अपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से ड्रॉ किया है. अगर आपने <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत ड्रॉ किया, तो आपसे अपने टैबलेट को किसी ईमेल खाते का इस्तेमाल करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड बाद फिर से कोशिश करें."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"आपने अपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से ड्रॉ किया है. अगर आपने <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत ड्रॉ किया, तो आपसे अपने फ़ोन को किसी ईमेल खाते का इस्तेमाल करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड बाद फिर से कोशिश करें."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"गलत SIM पिन कोड, अपने डिवाइस को अनलॉक करने के लिए अब आपको अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करना होगा."</string>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 4696001..4ff6862 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -66,8 +66,8 @@
<string name="kg_wrong_password" msgid="8060364776224836597">"चुकीचा पासवर्ड"</string>
<string name="kg_wrong_pin" msgid="4785660766909463466">"चुकीचा पिन"</string>
<plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
- <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> सेकंदात पुन्हा प्रयत्न करा.</item>
<item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> सेकंदांत पुन्हा प्रयत्न करा.</item>
+ <item quantity="one">एका सेकंदात पुन्हा प्रयत्न करा.</item>
</plurals>
<string name="kg_pattern_instructions" msgid="5547646893001491340">"तुमचा पॅटर्न काढा"</string>
<string name="kg_sim_pin_instructions" msgid="6389000973113699187">"सिम पिन एंटर करा"</string>
@@ -104,13 +104,13 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यपणे काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा फोन अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"सिम पिन कोड चुकीचा आहे तुम्ही आता तुमचे डिव्हाइस अनलॉक करण्यासाठी तुमच्या वाहकाशी संपर्क साधावा."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
- <item quantity="one">चुकीचा सिम पिन कोड, तुमच्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत.</item>
<item quantity="other">चुकीचा सिम पिन कोड, तुमच्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत.</item>
+ <item quantity="one"> चुकीचा सिम पिन कोड, तुमचे डिव्हाइस अनलॉक करण्यासाठी तुमच्या वाहकाशी संपर्क साधण्यापूर्वी तुमच्याकडे <xliff:g id="NUMBER_0">%d</xliff:g> प्रयत्न शिल्लक आहेत.</item>
</plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"सिम निरुपयोगी आहे. आपल्या वाहकाशी संपर्क साधा."</string>
<plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
- <item quantity="one">चुकीचा सिम PUK कोड, सिम कायमचे निरुपयोगी होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहे.</item>
<item quantity="other">चुकीचा सिम PUK कोड, सिम कायमचे निरुपयोगी होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत.</item>
+ <item quantity="one">चुकीचा सिम PUK कोड, सिम कायमचे निरुपयोगी होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER_0">%d</xliff:g> प्रयत्न शिल्लक आहे.</item>
</plurals>
<string name="kg_password_pin_failed" msgid="8769990811451236223">"सिम पिन ऑपरेशन अयशस्वी झाले!"</string>
<string name="kg_password_puk_failed" msgid="1331621440873439974">"सिम PUK कार्य अयशस्वी झाले!"</string>
@@ -130,25 +130,25 @@
<string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"प्रशासकाद्वारे लॉक केलेले डिव्हाइस"</string>
<string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"डिव्हाइस मॅन्युअली लॉक केले होते"</string>
<plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="71299470072448533">
- <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पॅटर्नची खात्री करा.</item>
<item quantity="other">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पॅटर्नची खात्री करा.</item>
+ <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_0">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पॅटर्नची खात्री करा.</item>
</plurals>
<plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="34586942088144385">
- <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पिनची खात्री करा.</item>
<item quantity="other">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पिन ची खात्री करा.</item>
+ <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_0">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पिनची खात्री करा.</item>
</plurals>
<plurals name="kg_prompt_reason_time_password" formatted="false" msgid="257297696215346527">
- <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item>
<item quantity="other">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item>
+ <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_0">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item>
</plurals>
<string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"ओळखले नाही"</string>
<string name="kg_face_not_recognized" msgid="6382535088345875294">"ओळखले नाही"</string>
<plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
- <item quantity="one">सिम पिन एंटर करा, तुमच्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहे.</item>
<item quantity="other">सिम पिन एंटर करा, तुमच्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत.</item>
+ <item quantity="one">सिम पिन एंटर करा. तुम्ही तुमचे डिव्हाइस अनलॉक करण्यासाठी तुमच्या वाहकाशी संपर्क साधण्यापूर्वी, तुमच्याकडे <xliff:g id="NUMBER_0">%d</xliff:g> प्रयत्न शिल्लक आहे.</item>
</plurals>
<plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352">
- <item quantity="one">सिम आता बंद केलेले आहे. सुरू ठेवण्यासाठी PUK कोड टाका. सिम कायमचे बंद होण्याआधी तुमच्याकडे <xliff:g id="_NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहे. तपशीलांसाठी वाहकाशी संपर्क साधा.</item>
<item quantity="other">सिम आता बंद केलेले आहे. सुरू ठेवण्यासाठी PUK कोड टाका. सिम कायमचे बंद होण्याआधी तुमच्याकडे <xliff:g id="_NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत. तपशीलांसाठी वाहकाशी संपर्क साधा.</item>
+ <item quantity="one">सिम आता बंद केलेले आहे. सुरू ठेवण्यासाठी PUK कोड टाका. सिम कायमचे बंद होण्याआधी तुमच्याकडे <xliff:g id="_NUMBER_0">%d</xliff:g> प्रयत्न शिल्लक आहे. तपशीलांसाठी वाहकाशी संपर्क साधा.</item>
</plurals>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
index fdca44d..e9bd638 100644
--- a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
@@ -27,7 +27,7 @@
<!-- Overload default clock widget parameters -->
<dimen name="widget_big_font_size">100dp</dimen>
- <dimen name="widget_label_font_size">16sp</dimen>
+ <dimen name="widget_label_font_size">18sp</dimen>
<!-- EmergencyCarrierArea overlap - amount to overlap the emergency button and carrier text.
Should be 0 on devices with plenty of room (e.g. tablets) -->
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 112dde6..8e00efe 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -42,23 +42,26 @@
<dimen name="eca_overlap">-10dip</dimen>
<!-- Slice header -->
- <dimen name="widget_title_font_size">22dp</dimen>
- <dimen name="header_subtitle_padding">4dp</dimen>
- <dimen name="header_icon_size">20dp</dimen>
+ <dimen name="widget_title_font_size">24dp</dimen>
+ <dimen name="header_subtitle_padding">12dp</dimen>
+ <dimen name="header_icon_size">16dp</dimen>
<!-- Slice subtitle -->
- <dimen name="widget_label_font_size">16dp</dimen>
+ <dimen name="widget_label_font_size">18dp</dimen>
<!-- Clock without header -->
- <dimen name="widget_big_font_size">64dp</dimen>
+ <dimen name="widget_big_font_size">54dp</dimen>
<dimen name="bottom_text_spacing_digital">0dp</dimen>
+ <dimen name="title_clock_padding">4dp</dimen>
<!-- Clock with header -->
- <dimen name="widget_small_font_size">22dp</dimen>
- <dimen name="widget_vertical_padding">32dp</dimen>
+ <dimen name="widget_small_font_size">@dimen/widget_title_font_size</dimen>
+ <dimen name="widget_vertical_padding">24dp</dimen>
+ <dimen name="widget_vertical_padding_with_header">32dp</dimen>
<dimen name="widget_vertical_padding_clock">12dp</dimen>
<!-- Subtitle paddings -->
<dimen name="widget_horizontal_padding">8dp</dimen>
- <dimen name="widget_icon_size">16dp</dimen>
+ <dimen name="widget_icon_size">20dp</dimen>
<dimen name="widget_icon_padding">8dp</dimen>
- <dimen name="subtitle_clock_padding">15dp</dimen>
+ <dimen name="subtitle_clock_padding">0dp</dimen>
+ <dimen name="header_row_font_size">14dp</dimen>
<!-- Notification shelf padding when dark -->
<dimen name="widget_bottom_separator_padding">-6dp</dimen>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 09a5295..9b47e14 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -112,6 +112,8 @@
whether it is valid, and to unlock the sim if it is valid. we display a
progress dialog in the meantime. this is the emssage. -->
<string name="keyguard_sim_unlock_progress_dialog_message">Unlocking SIM card\u2026</string>
+ <!-- Composes together the carrier name and the SIM card locked message. Example: CarrierName (SIM LOCKED) -->
+ <string name="keyguard_carrier_name_with_sim_locked_template" translatable="false"><xliff:g id="carrier">%s</xliff:g> (<xliff:g id="message">%s</xliff:g>)</string>
<!-- Time format strings for fall-back clock widget -->
<string name="keyguard_widget_12_hours_format" translatable="false">h:mm</string>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 6e4416a..137c30a 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -66,9 +66,16 @@
<item name="android:fontFeatureSettings">@*android:string/config_headlineFontFeatureSettings</item>
<item name="android:ellipsize">none</item>
</style>
- <style name="widget_big_bold">
+ <style name="widget_title_bold">
<item name="android:textStyle">bold</item>
- <item name="android:textSize">@dimen/widget_big_font_size</item>
+ <item name="android:textSize">@dimen/widget_title_font_size</item>
+ <item name="android:paddingBottom">@dimen/widget_vertical_padding_clock</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ <item name="android:ellipsize">none</item>
+ </style>
+ <style name="widget_small_bold">
+ <item name="android:textStyle">bold</item>
+ <item name="android:textSize">@dimen/widget_small_font_size</item>
<item name="android:paddingBottom">@dimen/bottom_text_spacing_digital</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:ellipsize">none</item>
@@ -108,6 +115,7 @@
<item name="android:layout_height">wrap_content</item>
<item name="android:lines">1</item>
<item name="android:textSize">@dimen/widget_label_font_size</item>
+ <item name="android:letterSpacing">0.02</item>
</style>
<style name="TextAppearance.Keyguard.BottomArea">
diff --git a/packages/SystemUI/res/anim/ic_bluetooth_transient_dot_left_animation.xml b/packages/SystemUI/res/anim/ic_bluetooth_transient_dot_left_animation.xml
deleted file mode 100644
index b5dd5c3..0000000
--- a/packages/SystemUI/res/anim/ic_bluetooth_transient_dot_left_animation.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<set
- xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="233"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="233"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="233"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="233"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- </set>
-</set>
diff --git a/packages/SystemUI/res/anim/ic_bluetooth_transient_dot_right_animation.xml b/packages/SystemUI/res/anim/ic_bluetooth_transient_dot_right_animation.xml
deleted file mode 100644
index 14704bf..0000000
--- a/packages/SystemUI/res/anim/ic_bluetooth_transient_dot_right_animation.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<set
- xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="233"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="233"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="233"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="233"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- </set>
-</set>
diff --git a/packages/SystemUI/res/anim/ic_caret_down_left_animation.xml b/packages/SystemUI/res/anim/ic_caret_down_left_animation.xml
deleted file mode 100644
index d465f19..0000000
--- a/packages/SystemUI/res/anim/ic_caret_down_left_animation.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<set
- xmlns:android="http://schemas.android.com/apk/res/android" >
- <objectAnimator
- android:duration="250"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 12.699,8.701 c 0.0,1.09767 0.0,5.48833 0.0,6.586"
- android:interpolator="@android:interpolator/fast_out_slow_in" />
- <objectAnimator
- android:duration="200"
- android:propertyName="rotation"
- android:valueFrom="-45.0"
- android:valueTo="45.0"
- android:valueType="floatType"
- android:interpolator="@interpolator/ic_caret_down_animation_interpolator_0" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_caret_down_right_animation.xml b/packages/SystemUI/res/anim/ic_caret_down_right_animation.xml
deleted file mode 100644
index 7a38ac3..0000000
--- a/packages/SystemUI/res/anim/ic_caret_down_right_animation.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<set
- xmlns:android="http://schemas.android.com/apk/res/android" >
- <objectAnimator
- android:duration="250"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 11.287,8.701 c 0.0,1.09767 0.0,5.48833 0.0,6.586"
- android:interpolator="@android:interpolator/fast_out_slow_in" />
- <objectAnimator
- android:duration="200"
- android:propertyName="rotation"
- android:valueFrom="45.0"
- android:valueTo="-45.0"
- android:valueType="floatType"
- android:interpolator="@interpolator/ic_caret_down_animation_interpolator_0" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_caret_up_left_animation.xml b/packages/SystemUI/res/anim/ic_caret_up_left_animation.xml
deleted file mode 100644
index 125a616..0000000
--- a/packages/SystemUI/res/anim/ic_caret_up_left_animation.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<set
- xmlns:android="http://schemas.android.com/apk/res/android" >
- <objectAnimator
- android:duration="250"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 12.699,15.287 c -0.04833,0.452 -0.04833,-7.03583 0.0,-6.586"
- android:interpolator="@android:interpolator/fast_out_slow_in" />
- <objectAnimator
- android:duration="200"
- android:propertyName="rotation"
- android:valueFrom="45.0"
- android:valueTo="-45.0"
- android:valueType="floatType"
- android:interpolator="@interpolator/ic_caret_up_animation_interpolator_0" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_caret_up_right_animation.xml b/packages/SystemUI/res/anim/ic_caret_up_right_animation.xml
deleted file mode 100644
index 3fd4df5..0000000
--- a/packages/SystemUI/res/anim/ic_caret_up_right_animation.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<set
- xmlns:android="http://schemas.android.com/apk/res/android" >
- <objectAnimator
- android:duration="250"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:pathData="M 11.287,15.287 c 0.04883,0.452 0.04883,-7.03583 0.0,-6.586"
- android:interpolator="@android:interpolator/fast_out_slow_in" />
- <objectAnimator
- android:duration="200"
- android:propertyName="rotation"
- android:valueFrom="-45.0"
- android:valueTo="45.0"
- android:valueType="floatType"
- android:interpolator="@interpolator/ic_caret_up_animation_interpolator_0" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_hotspot_transient_circle_1_animation.xml b/packages/SystemUI/res/anim/ic_hotspot_transient_circle_1_animation.xml
deleted file mode 100644
index 5e71847..0000000
--- a/packages/SystemUI/res/anim/ic_hotspot_transient_circle_1_animation.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<set
- xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="633"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- </set>
-</set>
diff --git a/packages/SystemUI/res/anim/ic_hotspot_transient_circle_2_animation.xml b/packages/SystemUI/res/anim/ic_hotspot_transient_circle_2_animation.xml
deleted file mode 100644
index 9081e6f..0000000
--- a/packages/SystemUI/res/anim/ic_hotspot_transient_circle_2_animation.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<set
- xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="200"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="633"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- </set>
-</set>
diff --git a/packages/SystemUI/res/anim/ic_hotspot_transient_circle_3_animation.xml b/packages/SystemUI/res/anim/ic_hotspot_transient_circle_3_animation.xml
deleted file mode 100644
index eaf5f05..0000000
--- a/packages/SystemUI/res/anim/ic_hotspot_transient_circle_3_animation.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<set
- xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="400"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="1.0"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="633"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="0.5"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="0.5"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- </set>
-</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_wifi_transient_wifi_1_animation.xml b/packages/SystemUI/res/anim/ic_signal_wifi_transient_wifi_1_animation.xml
deleted file mode 100644
index 919a4dd..0000000
--- a/packages/SystemUI/res/anim/ic_signal_wifi_transient_wifi_1_animation.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set
- xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="333"
- android:propertyName="pathData"
- android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueType="pathType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="pathData"
- android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueType="pathType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="316"
- android:propertyName="pathData"
- android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueType="pathType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="pathData"
- android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueType="pathType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="316"
- android:propertyName="pathData"
- android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueType="pathType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="pathData"
- android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:valueType="pathType"
- android:interpolator="@android:interpolator/linear" />
- </set>
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="333"
- android:propertyName="fillAlpha"
- android:valueFrom="0.0"
- android:valueTo="0.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="16"
- android:propertyName="fillAlpha"
- android:valueFrom="0.0"
- android:valueTo="1.0"
- android:valueType="floatType"
- android:interpolator="@android:interpolator/linear" />
- </set>
-</set>
diff --git a/packages/SystemUI/res/drawable-night/ic_media_projection_permission.xml b/packages/SystemUI/res/drawable-night/ic_media_projection_permission.xml
new file mode 100644
index 0000000..f20babf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-night/ic_media_projection_permission.xml
@@ -0,0 +1,26 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetLeft="2.5dp"
+ android:insetRight="2.5dp">
+ <vector android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M1,18v3h3C4,19.34 2.66,18 1,18zM1,14v2c2.76,0 5,2.24 5,5h2C8,17.13 4.87,14 1,14zM1,10v2c4.97,0 9,4.03 9,9h2C12,14.92 7.07,10 1,10zM21,3H3C1.9,3 1,3.9 1,5v3h2V5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2V5C23,3.9 22.1,3 21,3z"/>
+ <path android:fillColor="#FF0000" android:pathData="M19,7H5v1.63c3.96,1.28 7.09,4.41 8.37,8.37H19V7z"/>
+ </vector>
+</inset>
diff --git a/packages/SystemUI/res/drawable-night/status_bar_notification_section_header_clear_btn.xml b/packages/SystemUI/res/drawable-night/status_bar_notification_section_header_clear_btn.xml
new file mode 100644
index 0000000..c471b38
--- /dev/null
+++ b/packages/SystemUI/res/drawable-night/status_bar_notification_section_header_clear_btn.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="40dp"
+ android:height="40dp"
+ android:viewportWidth="40"
+ android:viewportHeight="40">
+ <path
+ android:fillColor="#9AA0A6"
+ android:pathData="M24.6667 16.2733L23.7267 15.3333L20 19.06L16.2734 15.3333L15.3334 16.2733L19.06 20L15.3334 23.7266L16.2734 24.6666L20 20.94L23.7267 24.6666L24.6667 23.7266L20.94 20L24.6667 16.2733Z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/bubble_dismiss_circle.xml b/packages/SystemUI/res/drawable/bubble_dismiss_circle.xml
new file mode 100644
index 0000000..1661bb2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/bubble_dismiss_circle.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (C) 2019 The Android Open 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.
+-->
+<!--
+ The transparent circle outline that encircles the bubbles when they're in the dismiss target.
+-->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+
+ <stroke
+ android:width="1dp"
+ android:color="#66FFFFFF" />
+
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/bubble_dismiss_icon.xml b/packages/SystemUI/res/drawable/bubble_dismiss_icon.xml
new file mode 100644
index 0000000..5c8de58
--- /dev/null
+++ b/packages/SystemUI/res/drawable/bubble_dismiss_icon.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2019 The Android Open 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.
+-->
+<!-- The 'X' bubble dismiss icon. This is just ic_close with a stroke. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z"
+ android:fillColor="#FFFFFFFF"
+ android:strokeColor="#FF000000"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/bubble_flyout.xml b/packages/SystemUI/res/drawable/bubble_flyout.xml
deleted file mode 100644
index afe5372..0000000
--- a/packages/SystemUI/res/drawable/bubble_flyout.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
- ~ Copyright (C) 2019 The Android Open 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
- -->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
- <item>
- <shape android:shape="rectangle">
- <solid android:color="?android:attr/colorBackgroundFloating" />
- <corners
- android:bottomLeftRadius="?android:attr/dialogCornerRadius"
- android:topLeftRadius="?android:attr/dialogCornerRadius"
- android:bottomRightRadius="?android:attr/dialogCornerRadius"
- android:topRightRadius="?android:attr/dialogCornerRadius" />
- <padding
- android:left="@dimen/bubble_flyout_pointer_size"
- android:right="@dimen/bubble_flyout_pointer_size" />
- </shape>
- </item>
-</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/button_border_selected.xml b/packages/SystemUI/res/drawable/button_border_selected.xml
index 1e40ade..01e7099 100644
--- a/packages/SystemUI/res/drawable/button_border_selected.xml
+++ b/packages/SystemUI/res/drawable/button_border_selected.xml
@@ -19,7 +19,7 @@
<solid
android:color="@color/notification_guts_selection_bg" />
<stroke
- android:width="2dp"
+ android:width="1dp"
android:color="@color/GM2_grey_300"/>
<corners android:radius="@dimen/rect_button_radius" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/button_border_unselected.xml b/packages/SystemUI/res/drawable/button_border_unselected.xml
index 4ea3764..b9c4ced 100644
--- a/packages/SystemUI/res/drawable/button_border_unselected.xml
+++ b/packages/SystemUI/res/drawable/button_border_unselected.xml
@@ -18,7 +18,7 @@
android:shape="rectangle"
android:color="@color/notification_guts_selection_bg">
<stroke
- android:width="2dp"
+ android:width="1dp"
android:color="@color/GM2_grey_300"/>
<corners android:radius="@dimen/rect_button_radius" />
diff --git a/packages/SystemUI/res/drawable/face_dialog_face_gray_to_checkmark.xml b/packages/SystemUI/res/drawable/face_dialog_dark_to_checkmark.xml
similarity index 98%
rename from packages/SystemUI/res/drawable/face_dialog_face_gray_to_checkmark.xml
rename to packages/SystemUI/res/drawable/face_dialog_dark_to_checkmark.xml
index b09f69b..fe19516 100644
--- a/packages/SystemUI/res/drawable/face_dialog_face_gray_to_checkmark.xml
+++ b/packages/SystemUI/res/drawable/face_dialog_dark_to_checkmark.xml
@@ -40,7 +40,7 @@
<path
android:name="_R_G_L_0_G_D_0_P_0"
android:fillAlpha="0"
- android:fillColor="@color/biometric_face_icon_gray"
+ android:fillColor="@color/biometric_dialog_accent"
android:fillType="nonZero"
android:pathData=" M-116 -16.5 C-116,-16.5 -31.25,68.5 -31.25,68.5 C-31.25,68.5 108.75,-71.5 108.75,-71.5 "
android:trimPathStart="0"
@@ -58,7 +58,7 @@
android:pathData=" M-116 -16.5 C-116,-16.5 -31.25,68.5 -31.25,68.5 C-31.25,68.5 108.75,-71.5 108.75,-71.5 "
android:strokeWidth="20"
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
+ android:strokeColor="@color/biometric_dialog_accent"
android:trimPathStart="0"
android:trimPathEnd="0"
android:trimPathOffset="0" />
@@ -68,7 +68,7 @@
android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
android:strokeWidth="2.5"
android:strokeAlpha="1"
- android:strokeColor="@color/biometric_face_icon_gray"
+ android:strokeColor="@color/biometric_dialog_accent"
android:trimPathStart="0"
android:trimPathEnd="1"
android:trimPathOffset="0" />
@@ -85,7 +85,7 @@
android:pathData=" M4.71 1.1 C3.71,2.12 2.32,2.75 0.79,2.75 C-2.25,2.75 -4.7,0.29 -4.7,-2.75 "
android:strokeWidth="2"
android:strokeAlpha="1"
- android:strokeColor="@color/biometric_face_icon_gray"
+ android:strokeColor="@color/biometric_dialog_accent"
android:trimPathStart="0"
android:trimPathEnd="1"
android:trimPathOffset="0" />
@@ -99,7 +99,7 @@
<path
android:name="_R_G_L_0_G_D_4_P_0"
android:fillAlpha="1"
- android:fillColor="@color/biometric_face_icon_gray"
+ android:fillColor="@color/biometric_dialog_accent"
android:fillType="nonZero"
android:pathData=" M-2.1 0 C-2.1,1.2 -1.2,2.1 0,2.1 C1.1,2.1 2.1,1.2 2.1,0 C2.1,-1.2 1.2,-2.1 0,-2.1 C-1.2,-2.1 -2.1,-1.2 -2.1,0c " />
</group>
@@ -112,7 +112,7 @@
<path
android:name="_R_G_L_0_G_D_5_P_0"
android:fillAlpha="1"
- android:fillColor="@color/biometric_face_icon_gray"
+ android:fillColor="@color/biometric_dialog_accent"
android:fillType="nonZero"
android:pathData=" M-2.1 0 C-2.1,1.2 -1.2,2.1 0,2.1 C1.2,2.1 2.1,1.2 2.1,0 C2.1,-1.2 1.2,-2.1 0,-2.1 C-1.2,-2.1 -2.1,-1.2 -2.1,0c " />
</group>
@@ -125,7 +125,7 @@
<path
android:name="_R_G_L_0_G_D_6_P_0"
android:fillAlpha="1"
- android:fillColor="@color/biometric_face_icon_gray"
+ android:fillColor="@color/biometric_dialog_accent"
android:fillType="nonZero"
android:pathData=" M2.6 3.25 C2.6,3.25 -2.6,3.25 -2.6,3.25 C-2.6,3.25 -2.6,1.25 -2.6,1.25 C-2.6,1.25 0.6,1.25 0.6,1.25 C0.6,1.25 0.6,-3.25 0.6,-3.25 C0.6,-3.25 2.6,-3.25 2.6,-3.25 C2.6,-3.25 2.6,3.25 2.6,3.25c " />
</group>
@@ -386,8 +386,8 @@
android:duration="67"
android:propertyName="strokeColor"
android:startOffset="0"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="@color/biometric_face_icon_gray"
+ android:valueFrom="@color/biometric_dialog_accent"
+ android:valueTo="@color/biometric_dialog_accent"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -397,8 +397,8 @@
android:duration="17"
android:propertyName="strokeColor"
android:startOffset="67"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="?android:attr/colorAccent"
+ android:valueFrom="@color/biometric_dialog_accent"
+ android:valueTo="@color/biometric_dialog_accent"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
diff --git a/packages/SystemUI/res/drawable/face_dialog_face_to_error.xml b/packages/SystemUI/res/drawable/face_dialog_dark_to_error.xml
similarity index 95%
rename from packages/SystemUI/res/drawable/face_dialog_face_to_error.xml
rename to packages/SystemUI/res/drawable/face_dialog_dark_to_error.xml
index a96d21a..0c05019 100644
--- a/packages/SystemUI/res/drawable/face_dialog_face_to_error.xml
+++ b/packages/SystemUI/res/drawable/face_dialog_dark_to_error.xml
@@ -36,7 +36,7 @@
android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
android:strokeWidth="2.5"
android:strokeAlpha="1"
- android:strokeColor="@color/biometric_face_icon_gray"
+ android:strokeColor="@color/biometric_dialog_gray"
android:trimPathStart="0"
android:trimPathEnd="1"
android:trimPathOffset="0" />
@@ -45,7 +45,7 @@
android:pathData=" M33.75 42.75 C32.75,43.76 31.37,44.39 29.83,44.39 C26.8,44.39 24.34,41.93 24.34,38.9 "
android:strokeWidth="2"
android:strokeAlpha="1"
- android:strokeColor="@color/biometric_face_icon_gray"
+ android:strokeColor="@color/biometric_dialog_gray"
android:trimPathStart="0"
android:trimPathEnd="1"
android:trimPathOffset="0" />
@@ -58,7 +58,7 @@
<path
android:name="_R_G_L_0_G_D_2_P_0"
android:fillAlpha="1"
- android:fillColor="@color/biometric_face_icon_gray"
+ android:fillColor="@color/biometric_dialog_gray"
android:fillType="nonZero"
android:pathData=" M-2.1 0 C-2.1,1.2 -1.2,2.1 0,2.1 C1.1,2.1 2.1,1.2 2.1,0 C2.1,-1.2 1.2,-2.1 0,-2.1 C-1.2,-2.1 -2.1,-1.2 -2.1,0c " />
</group>
@@ -71,7 +71,7 @@
<path
android:name="_R_G_L_0_G_D_3_P_0"
android:fillAlpha="1"
- android:fillColor="@color/biometric_face_icon_gray"
+ android:fillColor="@color/biometric_dialog_gray"
android:fillType="nonZero"
android:pathData=" M-2.1 0 C-2.1,1.2 -1.2,2.1 0,2.1 C1.2,2.1 2.1,1.2 2.1,0 C2.1,-1.2 1.2,-2.1 0,-2.1 C-1.2,-2.1 -2.1,-1.2 -2.1,0c " />
</group>
@@ -82,7 +82,7 @@
<path
android:name="_R_G_L_0_G_D_4_P_0"
android:fillAlpha="1"
- android:fillColor="@color/biometric_face_icon_gray"
+ android:fillColor="@color/biometric_dialog_gray"
android:fillType="nonZero"
android:pathData=" M2.6 3.25 C2.6,3.25 -2.6,3.25 -2.6,3.25 C-2.6,3.25 -2.6,1.25 -2.6,1.25 C-2.6,1.25 0.6,1.25 0.6,1.25 C0.6,1.25 0.6,-3.25 0.6,-3.25 C0.6,-3.25 2.6,-3.25 2.6,-3.25 C2.6,-3.25 2.6,3.25 2.6,3.25c " />
</group>
@@ -99,8 +99,8 @@
android:duration="50"
android:propertyName="strokeColor"
android:startOffset="0"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="@color/biometric_face_icon_gray"
+ android:valueFrom="@color/biometric_dialog_gray"
+ android:valueTo="@color/biometric_dialog_gray"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -110,8 +110,8 @@
android:duration="17"
android:propertyName="strokeColor"
android:startOffset="50"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="?android:attr/colorError"
+ android:valueFrom="@color/biometric_dialog_gray"
+ android:valueTo="@color/biometric_dialog_error"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -127,8 +127,8 @@
android:duration="50"
android:propertyName="strokeColor"
android:startOffset="0"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="@color/biometric_face_icon_gray"
+ android:valueFrom="@color/biometric_dialog_gray"
+ android:valueTo="@color/biometric_dialog_gray"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -138,8 +138,8 @@
android:duration="17"
android:propertyName="strokeColor"
android:startOffset="50"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="?android:attr/colorError"
+ android:valueFrom="@color/biometric_dialog_gray"
+ android:valueTo="@color/biometric_dialog_error"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -369,8 +369,8 @@
android:duration="50"
android:propertyName="fillColor"
android:startOffset="0"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="@color/biometric_face_icon_gray"
+ android:valueFrom="@color/biometric_dialog_gray"
+ android:valueTo="@color/biometric_dialog_gray"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -380,8 +380,8 @@
android:duration="17"
android:propertyName="fillColor"
android:startOffset="50"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="?android:attr/colorError"
+ android:valueFrom="@color/biometric_dialog_gray"
+ android:valueTo="@color/biometric_dialog_error"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
diff --git a/packages/SystemUI/res/drawable/face_dialog_error_to_face.xml b/packages/SystemUI/res/drawable/face_dialog_error_to_idle.xml
similarity index 81%
rename from packages/SystemUI/res/drawable/face_dialog_error_to_face.xml
rename to packages/SystemUI/res/drawable/face_dialog_error_to_idle.xml
index 75311f4..d3cee25 100644
--- a/packages/SystemUI/res/drawable/face_dialog_error_to_face.xml
+++ b/packages/SystemUI/res/drawable/face_dialog_error_to_idle.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright (C) 2018 The Android Open Source Project
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -23,69 +23,61 @@
android:viewportWidth="60"
android:viewportHeight="60">
<group android:name="_R_G">
- <group
- android:name="_R_G_L_0_G_N_1_T_0"
- android:translateX="30"
- android:translateY="30">
+ <group android:name="_R_G_L_0_G">
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
+ android:strokeWidth="2.5"
+ android:strokeAlpha="1"
+ android:strokeColor="@color/biometric_dialog_error"
+ android:trimPathStart="0"
+ android:trimPathEnd="1"
+ android:trimPathOffset="0" />
+ <path
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:pathData=" M34.78 38.76 C33.83,38.75 31.54,38.75 30.01,38.75 C26.97,38.75 26.14,38.75 24.3,38.76 "
+ android:strokeWidth="2.5"
+ android:strokeAlpha="1"
+ android:strokeColor="@color/biometric_dialog_error"
+ android:trimPathStart="0.34"
+ android:trimPathEnd="0.5700000000000001"
+ android:trimPathOffset="0" />
<group
- android:name="_R_G_L_0_G"
- android:translateX="-30"
- android:translateY="-30">
+ android:name="_R_G_L_0_G_D_2_P_0_G_0_T_0"
+ android:scaleX="0.3"
+ android:scaleY="0.3"
+ android:translateX="37.788"
+ android:translateY="19.53">
<path
- android:name="_R_G_L_0_G_D_0_P_0"
- android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
- android:strokeWidth="2.5"
- android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorError"
- android:trimPathStart="0"
- android:trimPathEnd="1"
- android:trimPathOffset="0" />
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:fillAlpha="0"
+ android:fillColor="@color/biometric_dialog_gray"
+ android:fillType="nonZero"
+ android:pathData=" M-2.1 0 C-2.1,1.2 -1.2,2.1 0,2.1 C1.1,2.1 2.1,1.2 2.1,0 C2.1,-1.2 1.2,-2.1 0,-2.1 C-1.2,-2.1 -2.1,-1.2 -2.1,0c " />
+ </group>
+ <group
+ android:name="_R_G_L_0_G_D_3_P_0_G_0_T_0"
+ android:scaleX="0.3"
+ android:scaleY="0.3"
+ android:translateX="22.005"
+ android:translateY="19.51">
<path
- android:name="_R_G_L_0_G_D_1_P_0"
- android:pathData=" M34.78 38.76 C33.83,38.75 31.54,38.75 30.01,38.75 C26.97,38.75 26.14,38.75 24.3,38.76 "
- android:strokeWidth="2.5"
- android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorError"
- android:trimPathStart="0.34"
- android:trimPathEnd="0.5700000000000001"
- android:trimPathOffset="0" />
- <group
- android:name="_R_G_L_0_G_D_2_P_0_G_0_T_0"
- android:scaleX="0.3"
- android:scaleY="0.3"
- android:translateX="37.788"
- android:translateY="19.53">
- <path
- android:name="_R_G_L_0_G_D_2_P_0"
- android:fillAlpha="0"
- android:fillColor="@color/biometric_face_icon_gray"
- android:fillType="nonZero"
- android:pathData=" M-2.1 0 C-2.1,1.2 -1.2,2.1 0,2.1 C1.1,2.1 2.1,1.2 2.1,0 C2.1,-1.2 1.2,-2.1 0,-2.1 C-1.2,-2.1 -2.1,-1.2 -2.1,0c " />
- </group>
- <group
- android:name="_R_G_L_0_G_D_3_P_0_G_0_T_0"
- android:scaleX="0.3"
- android:scaleY="0.3"
- android:translateX="22.005"
- android:translateY="19.51">
- <path
- android:name="_R_G_L_0_G_D_3_P_0"
- android:fillAlpha="0"
- android:fillColor="@color/biometric_face_icon_gray"
- android:fillType="nonZero"
- android:pathData=" M-2.1 0 C-2.1,1.2 -1.2,2.1 0,2.1 C1.2,2.1 2.1,1.2 2.1,0 C2.1,-1.2 1.2,-2.1 0,-2.1 C-1.2,-2.1 -2.1,-1.2 -2.1,0c " />
- </group>
- <group
- android:name="_R_G_L_0_G_D_4_P_0_G_0_T_0"
- android:translateX="30.3"
- android:translateY="29.215">
- <path
- android:name="_R_G_L_0_G_D_4_P_0"
- android:fillAlpha="1"
- android:fillColor="?android:attr/colorError"
- android:fillType="nonZero"
- android:pathData=" M0.9 3.25 C0.9,3.25 -1.5,3.25 -1.5,3.25 C-1.5,3.25 -1.5,1.25 -1.5,1.25 C-1.5,1.25 -1.5,1.25 -1.5,1.25 C-1.5,1.25 -1.5,-11.71 -1.5,-11.71 C-1.5,-11.71 0.9,-11.71 0.9,-11.71 C0.9,-11.71 0.9,3.25 0.9,3.25c " />
- </group>
+ android:name="_R_G_L_0_G_D_3_P_0"
+ android:fillAlpha="0"
+ android:fillColor="@color/biometric_dialog_gray"
+ android:fillType="nonZero"
+ android:pathData=" M-2.1 0 C-2.1,1.2 -1.2,2.1 0,2.1 C1.2,2.1 2.1,1.2 2.1,0 C2.1,-1.2 1.2,-2.1 0,-2.1 C-1.2,-2.1 -2.1,-1.2 -2.1,0c " />
+ </group>
+ <group
+ android:name="_R_G_L_0_G_D_4_P_0_G_0_T_0"
+ android:translateX="30.3"
+ android:translateY="29.215">
+ <path
+ android:name="_R_G_L_0_G_D_4_P_0"
+ android:fillAlpha="1"
+ android:fillColor="@color/biometric_dialog_error"
+ android:fillType="nonZero"
+ android:pathData=" M0.9 3.25 C0.9,3.25 -1.5,3.25 -1.5,3.25 C-1.5,3.25 -1.5,1.25 -1.5,1.25 C-1.5,1.25 -1.5,1.25 -1.5,1.25 C-1.5,1.25 -1.5,-11.71 -1.5,-11.71 C-1.5,-11.71 0.9,-11.71 0.9,-11.71 C0.9,-11.71 0.9,3.25 0.9,3.25c " />
</group>
</group>
</group>
@@ -99,8 +91,8 @@
android:duration="83"
android:propertyName="strokeColor"
android:startOffset="0"
- android:valueFrom="?android:attr/colorError"
- android:valueTo="?android:attr/colorError"
+ android:valueFrom="@color/biometric_dialog_error"
+ android:valueTo="@color/biometric_dialog_error"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -110,8 +102,8 @@
android:duration="17"
android:propertyName="strokeColor"
android:startOffset="83"
- android:valueFrom="?android:attr/colorError"
- android:valueTo="@color/biometric_face_icon_gray"
+ android:valueFrom="@color/biometric_dialog_error"
+ android:valueTo="@color/biometric_dialog_gray"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -127,8 +119,8 @@
android:duration="83"
android:propertyName="strokeColor"
android:startOffset="0"
- android:valueFrom="?android:attr/colorError"
- android:valueTo="?android:attr/colorError"
+ android:valueFrom="@color/biometric_dialog_error"
+ android:valueTo="@color/biometric_dialog_error"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -138,8 +130,8 @@
android:duration="17"
android:propertyName="strokeColor"
android:startOffset="83"
- android:valueFrom="?android:attr/colorError"
- android:valueTo="@color/biometric_face_icon_gray"
+ android:valueFrom="@color/biometric_dialog_error"
+ android:valueTo="@color/biometric_dialog_gray"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -435,8 +427,8 @@
android:duration="83"
android:propertyName="fillColor"
android:startOffset="0"
- android:valueFrom="?android:attr/colorError"
- android:valueTo="?android:attr/colorError"
+ android:valueFrom="@color/biometric_dialog_error"
+ android:valueTo="@color/biometric_dialog_error"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -446,8 +438,8 @@
android:duration="17"
android:propertyName="fillColor"
android:startOffset="83"
- android:valueFrom="?android:attr/colorError"
- android:valueTo="@color/biometric_face_icon_gray"
+ android:valueFrom="@color/biometric_dialog_error"
+ android:valueTo="@color/biometric_dialog_gray"
android:valueType="colorType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -505,7 +497,7 @@
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator
- android:duration="233"
+ android:duration="267"
android:propertyName="translateX"
android:startOffset="0"
android:valueFrom="0"
diff --git a/packages/SystemUI/res/drawable/face_dialog_face_blue_to_checkmark.xml b/packages/SystemUI/res/drawable/face_dialog_face_blue_to_checkmark.xml
deleted file mode 100644
index e4ace67..0000000
--- a/packages/SystemUI/res/drawable/face_dialog_face_blue_to_checkmark.xml
+++ /dev/null
@@ -1,637 +0,0 @@
-<?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
- -->
-
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:aapt="http://schemas.android.com/aapt">
- <aapt:attr name="android:drawable">
- <vector
- android:width="60dp"
- android:height="60dp"
- android:viewportWidth="60"
- android:viewportHeight="60">
- <group android:name="_R_G">
- <group
- android:name="_R_G_L_0_G_N_2_T_0"
- android:translateX="30"
- android:translateY="30">
- <group
- android:name="_R_G_L_0_G"
- android:translateX="-30"
- android:translateY="-30">
- <group
- android:name="_R_G_L_0_G_D_0_P_0_G_0_T_0"
- android:scaleX="0.08"
- android:scaleY="0.08"
- android:translateX="30.1"
- android:translateY="30.083">
- <path
- android:name="_R_G_L_0_G_D_0_P_0"
- android:fillAlpha="0"
- android:fillColor="?android:attr/colorAccent"
- android:fillType="nonZero"
- android:pathData=" M-116 -16.5 C-116,-16.5 -31.25,68.5 -31.25,68.5 C-31.25,68.5 108.75,-71.5 108.75,-71.5 "
- android:trimPathStart="0"
- android:trimPathEnd="0"
- android:trimPathOffset="0" />
- </group>
- <group
- android:name="_R_G_L_0_G_D_1_P_0_G_0_T_0"
- android:scaleX="0.08"
- android:scaleY="0.08"
- android:translateX="30.1"
- android:translateY="30.083">
- <path
- android:name="_R_G_L_0_G_D_1_P_0"
- android:pathData=" M-116 -16.5 C-116,-16.5 -31.25,68.5 -31.25,68.5 C-31.25,68.5 108.75,-71.5 108.75,-71.5 "
- android:strokeWidth="20"
- android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
- android:trimPathStart="0"
- android:trimPathEnd="0"
- android:trimPathOffset="0" />
- </group>
- <path
- android:name="_R_G_L_0_G_D_2_P_0"
- android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
- android:strokeWidth="2.5"
- android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
- android:trimPathStart="0"
- android:trimPathEnd="1"
- android:trimPathOffset="0" />
- <group
- android:name="_R_G_L_0_G_D_3_P_0_G_0_T_0"
- android:pivotX="1.05"
- android:pivotY="-9.891"
- android:scaleX="1"
- android:scaleY="1"
- android:translateX="29.044"
- android:translateY="41.647">
- <path
- android:name="_R_G_L_0_G_D_3_P_0"
- android:pathData=" M4.71 1.1 C3.71,2.12 2.32,2.75 0.79,2.75 C-2.25,2.75 -4.7,0.29 -4.7,-2.75 "
- android:strokeWidth="2"
- android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
- android:trimPathStart="0"
- android:trimPathEnd="1"
- android:trimPathOffset="0" />
- </group>
- <group
- android:name="_R_G_L_0_G_D_4_P_0_G_0_T_0"
- android:scaleX="1"
- android:scaleY="1"
- android:translateX="41.1"
- android:translateY="23.8">
- <path
- android:name="_R_G_L_0_G_D_4_P_0"
- android:fillAlpha="1"
- android:fillColor="?android:attr/colorAccent"
- android:fillType="nonZero"
- android:pathData=" M-2.1 0 C-2.1,1.2 -1.2,2.1 0,2.1 C1.1,2.1 2.1,1.2 2.1,0 C2.1,-1.2 1.2,-2.1 0,-2.1 C-1.2,-2.1 -2.1,-1.2 -2.1,0c " />
- </group>
- <group
- android:name="_R_G_L_0_G_D_5_P_0_G_0_T_0"
- android:scaleX="1"
- android:scaleY="1"
- android:translateX="18.6"
- android:translateY="23.8">
- <path
- android:name="_R_G_L_0_G_D_5_P_0"
- android:fillAlpha="1"
- android:fillColor="?android:attr/colorAccent"
- android:fillType="nonZero"
- android:pathData=" M-2.1 0 C-2.1,1.2 -1.2,2.1 0,2.1 C1.2,2.1 2.1,1.2 2.1,0 C2.1,-1.2 1.2,-2.1 0,-2.1 C-1.2,-2.1 -2.1,-1.2 -2.1,0c " />
- </group>
- <group
- android:name="_R_G_L_0_G_D_6_P_0_G_0_T_0"
- android:scaleX="1"
- android:scaleY="1"
- android:translateX="30.727"
- android:translateY="31.703">
- <path
- android:name="_R_G_L_0_G_D_6_P_0"
- android:fillAlpha="1"
- android:fillColor="?android:attr/colorAccent"
- android:fillType="nonZero"
- android:pathData=" M2.6 3.25 C2.6,3.25 -2.6,3.25 -2.6,3.25 C-2.6,3.25 -2.6,1.25 -2.6,1.25 C-2.6,1.25 0.6,1.25 0.6,1.25 C0.6,1.25 0.6,-3.25 0.6,-3.25 C0.6,-3.25 2.6,-3.25 2.6,-3.25 C2.6,-3.25 2.6,3.25 2.6,3.25c " />
- </group>
- </group>
- </group>
- </group>
- <group android:name="time_group" />
- </vector>
- </aapt:attr>
- <target android:name="_R_G_L_0_G_D_0_P_0_G_0_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="33"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0.08"
- android:valueTo="0.08"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.537,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="33"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0.08"
- android:valueTo="0.08"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.537,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="167"
- android:propertyName="scaleX"
- android:startOffset="33"
- android:valueFrom="0.08"
- android:valueTo="0.12789"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.537,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="167"
- android:propertyName="scaleY"
- android:startOffset="33"
- android:valueFrom="0.08"
- android:valueTo="0.12789"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.537,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="100"
- android:propertyName="scaleX"
- android:startOffset="200"
- android:valueFrom="0.12789"
- android:valueTo="0.12241"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.441,0 0.533,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="100"
- android:propertyName="scaleY"
- android:startOffset="200"
- android:valueFrom="0.12789"
- android:valueTo="0.12241"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.441,0 0.533,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="scaleX"
- android:startOffset="300"
- android:valueFrom="0.12241"
- android:valueTo="0.125"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.424,0 0.486,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="scaleY"
- android:startOffset="300"
- android:valueFrom="0.12241"
- android:valueTo="0.125"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.424,0 0.486,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_0_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="33"
- android:propertyName="trimPathEnd"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.292,0 0.155,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="trimPathEnd"
- android:startOffset="33"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.292,0 0.155,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_1_P_0_G_0_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="33"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0.08"
- android:valueTo="0.08"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.537,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="33"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0.08"
- android:valueTo="0.08"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.537,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="167"
- android:propertyName="scaleX"
- android:startOffset="33"
- android:valueFrom="0.08"
- android:valueTo="0.12789"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.537,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="167"
- android:propertyName="scaleY"
- android:startOffset="33"
- android:valueFrom="0.08"
- android:valueTo="0.12789"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.537,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="100"
- android:propertyName="scaleX"
- android:startOffset="200"
- android:valueFrom="0.12789"
- android:valueTo="0.12241"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.441,0 0.533,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="100"
- android:propertyName="scaleY"
- android:startOffset="200"
- android:valueFrom="0.12789"
- android:valueTo="0.12241"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.441,0 0.533,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="scaleX"
- android:startOffset="300"
- android:valueFrom="0.12241"
- android:valueTo="0.125"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.424,0 0.486,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="scaleY"
- android:startOffset="300"
- android:valueFrom="0.12241"
- android:valueTo="0.125"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.424,0 0.486,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_1_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="33"
- android:propertyName="trimPathEnd"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.292,0 0.155,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="trimPathEnd"
- android:startOffset="33"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.292,0 0.155,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_2_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="67"
- android:propertyName="strokeColor"
- android:startOffset="0"
- android:valueFrom="?android:attr/colorAccent"
- android:valueTo="?android:attr/colorAccent"
- android:valueType="colorType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="17"
- android:propertyName="strokeColor"
- android:startOffset="67"
- android:valueFrom="?android:attr/colorAccent"
- android:valueTo="?android:attr/colorAccent"
- android:valueType="colorType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_3_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="50"
- android:propertyName="strokeAlpha"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_3_P_0_G_0_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="67"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.65"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.65"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_3_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="83"
- android:propertyName="trimPathStart"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="0.5"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_3_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="83"
- android:propertyName="trimPathEnd"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.5"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_4_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="50"
- android:propertyName="fillAlpha"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_4_P_0_G_0_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="83"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="83"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_5_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="50"
- android:propertyName="fillAlpha"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_5_P_0_G_0_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="83"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="83"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_6_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="50"
- android:propertyName="fillAlpha"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_6_P_0_G_0_T_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="83"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.287,0.12 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- <objectAnimator
- android:duration="83"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.287,0.12 0.667,1 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="383"
- android:propertyName="translateX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" />
- </set>
- </aapt:attr>
- </target>
-</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/face_dialog_face_gray_to_face_blue.xml b/packages/SystemUI/res/drawable/face_dialog_face_gray_to_face_blue.xml
deleted file mode 100644
index 9259dc7..0000000
--- a/packages/SystemUI/res/drawable/face_dialog_face_gray_to_face_blue.xml
+++ /dev/null
@@ -1,178 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright (C) 2019 The Android Open 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
- -->
-
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:aapt="http://schemas.android.com/aapt">
- <aapt:attr name="android:drawable">
- <vector
- android:width="60dp"
- android:height="60dp"
- android:viewportHeight="60"
- android:viewportWidth="60">
- <group android:name="_R_G">
- <group
- android:name="_R_G_L_0_G_N_1_T_0"
- android:translateX="30"
- android:translateY="30">
- <group
- android:name="_R_G_L_0_G"
- android:translateX="-30"
- android:translateY="-30">
- <path
- android:name="_R_G_L_0_G_D_0_P_0"
- android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
- android:strokeAlpha="1"
- android:strokeColor="@color/biometric_face_icon_gray"
- android:strokeLineCap="round"
- android:strokeLineJoin="round"
- android:strokeWidth="2.5"
- android:trimPathEnd="1"
- android:trimPathOffset="0"
- android:trimPathStart="0" />
- <path
- android:name="_R_G_L_0_G_D_1_P_0"
- android:pathData=" M33.75 42.75 C32.75,43.76 31.37,44.39 29.83,44.39 C26.8,44.39 24.34,41.93 24.34,38.9 "
- android:strokeAlpha="1"
- android:strokeColor="@color/biometric_face_icon_gray"
- android:strokeLineCap="round"
- android:strokeLineJoin="round"
- android:strokeWidth="2"
- android:trimPathEnd="1"
- android:trimPathOffset="0"
- android:trimPathStart="0" />
- <path
- android:name="_R_G_L_0_G_D_2_P_0"
- android:fillAlpha="1"
- android:fillColor="@color/biometric_face_icon_gray"
- android:fillType="nonZero"
- android:pathData=" M39 23.8 C39,25 39.9,25.9 41.1,25.9 C42.2,25.9 43.2,25 43.2,23.8 C43.2,22.6 42.3,21.7 41.1,21.7 C39.9,21.7 39,22.6 39,23.8c " />
- <path
- android:name="_R_G_L_0_G_D_3_P_0"
- android:fillAlpha="1"
- android:fillColor="@color/biometric_face_icon_gray"
- android:fillType="nonZero"
- android:pathData=" M16.5 23.8 C16.5,25 17.4,25.9 18.6,25.9 C19.8,25.9 20.7,25 20.7,23.8 C20.7,22.6 19.8,21.7 18.6,21.7 C17.4,21.7 16.5,22.6 16.5,23.8c " />
- <path
- android:name="_R_G_L_0_G_D_4_P_0"
- android:fillAlpha="1"
- android:fillColor="@color/biometric_face_icon_gray"
- android:fillType="nonZero"
- android:pathData=" M32.9 34.7 C32.9,34.7 27.7,34.7 27.7,34.7 C27.7,34.7 27.7,32.7 27.7,32.7 C27.7,32.7 30.9,32.7 30.9,32.7 C30.9,32.7 30.9,28.2 30.9,28.2 C30.9,28.2 32.9,28.2 32.9,28.2 C32.9,28.2 32.9,34.7 32.9,34.7c " />
- </group>
- </group>
- </group>
- <group android:name="time_group" />
- </vector>
- </aapt:attr>
- <target android:name="_R_G_L_0_G_D_0_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="33"
- android:propertyName="strokeColor"
- android:startOffset="0"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="?android:attr/colorAccent"
- android:valueType="colorType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_1_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="33"
- android:propertyName="strokeColor"
- android:startOffset="0"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="?android:attr/colorAccent"
- android:valueType="colorType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_2_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="33"
- android:propertyName="fillColor"
- android:startOffset="0"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="?android:attr/colorAccent"
- android:valueType="colorType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_3_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="33"
- android:propertyName="fillColor"
- android:startOffset="0"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="?android:attr/colorAccent"
- android:valueType="colorType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_D_4_P_0">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="33"
- android:propertyName="fillColor"
- android:startOffset="0"
- android:valueFrom="@color/biometric_face_icon_gray"
- android:valueTo="?android:attr/colorAccent"
- android:valueType="colorType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="50"
- android:propertyName="translateX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" />
- </set>
- </aapt:attr>
- </target>
-</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/face_dialog_idle_static.xml b/packages/SystemUI/res/drawable/face_dialog_idle_static.xml
new file mode 100644
index 0000000..6ad8e83
--- /dev/null
+++ b/packages/SystemUI/res/drawable/face_dialog_idle_static.xml
@@ -0,0 +1,276 @@
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector
+ android:width="60dp"
+ android:height="60dp"
+ android:viewportWidth="60"
+ android:viewportHeight="60">
+ <group android:name="_R_G">
+ <group
+ android:name="_R_G_L_0_G"
+ android:pivotX="30"
+ android:pivotY="30"
+ android:scaleX="1.03"
+ android:scaleY="1.03">
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
+ android:strokeWidth="2.5"
+ android:strokeAlpha="1.0"
+ android:strokeColor="@color/biometric_dialog_gray"
+ android:trimPathStart="0"
+ android:trimPathEnd="1"
+ android:trimPathOffset="0" />
+ <path
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:pathData=" M33.75 42.75 C32.75,43.77 31.37,44.39 29.83,44.39 C26.8,44.39 24.34,41.93 24.34,38.9 "
+ android:strokeWidth="2"
+ android:strokeAlpha="1.0"
+ android:strokeColor="@color/biometric_dialog_gray"
+ android:trimPathStart="0"
+ android:trimPathEnd="1"
+ android:trimPathOffset="0" />
+ <path
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:fillAlpha="1.0"
+ android:fillColor="@color/biometric_dialog_gray"
+ android:fillType="nonZero"
+ android:pathData=" M39 23.8 C39,25 39.9,25.9 41.1,25.9 C42.2,25.9 43.2,25 43.2,23.8 C43.2,22.6 42.3,21.7 41.1,21.7 C39.9,21.7 39,22.6 39,23.8c " />
+ <path
+ android:name="_R_G_L_0_G_D_3_P_0"
+ android:fillAlpha="1.0"
+ android:fillColor="@color/biometric_dialog_gray"
+ android:fillType="nonZero"
+ android:pathData=" M16.5 23.8 C16.5,25 17.4,25.9 18.6,25.9 C19.8,25.9 20.7,25 20.7,23.8 C20.7,22.6 19.8,21.7 18.6,21.7 C17.4,21.7 16.5,22.6 16.5,23.8c " />
+ <path
+ android:name="_R_G_L_0_G_D_4_P_0"
+ android:fillAlpha="1.0"
+ android:fillColor="@color/biometric_dialog_gray"
+ android:fillType="nonZero"
+ android:pathData=" M33.33 34.95 C33.33,34.95 28.13,34.95 28.13,34.95 C28.13,34.95 28.13,32.95 28.13,32.95 C28.13,32.95 31.33,32.95 31.33,32.95 C31.33,32.95 31.33,28.45 31.33,28.45 C31.33,28.45 33.33,28.45 33.33,28.45 C33.33,28.45 33.33,34.95 33.33,34.95c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_0_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="strokeAlpha"
+ android:startOffset="0"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.118,1.266 0.419,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="strokeAlpha"
+ android:startOffset="500"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_1_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="strokeAlpha"
+ android:startOffset="0"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.118,1.266 0.419,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="strokeAlpha"
+ android:startOffset="500"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_2_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.118,1.266 0.419,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="fillAlpha"
+ android:startOffset="500"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_3_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.118,1.266 0.419,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="fillAlpha"
+ android:startOffset="500"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_4_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.118,1.266 0.419,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="fillAlpha"
+ android:startOffset="500"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="1.03"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="1.03"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="scaleX"
+ android:startOffset="500"
+ android:valueFrom="1"
+ android:valueTo="1.03"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.204,0.46 0.568,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="scaleY"
+ android:startOffset="500"
+ android:valueFrom="1"
+ android:valueTo="1.03"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.204,0.46 0.568,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="1017"
+ android:propertyName="translateX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType" />
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/face_dialog_pulse_dark_to_light.xml b/packages/SystemUI/res/drawable/face_dialog_pulse_dark_to_light.xml
new file mode 100644
index 0000000..427be14
--- /dev/null
+++ b/packages/SystemUI/res/drawable/face_dialog_pulse_dark_to_light.xml
@@ -0,0 +1,183 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector
+ android:width="60dp"
+ android:height="60dp"
+ android:viewportWidth="60"
+ android:viewportHeight="60">
+ <group android:name="_R_G">
+ <group
+ android:name="_R_G_L_0_G"
+ android:pivotX="30"
+ android:pivotY="30"
+ android:scaleX="1"
+ android:scaleY="1">
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
+ android:strokeWidth="2.5"
+ android:strokeAlpha="1"
+ android:strokeColor="@color/biometric_dialog_accent"
+ android:trimPathStart="0"
+ android:trimPathEnd="1"
+ android:trimPathOffset="0" />
+ <path
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:pathData=" M33.75 42.75 C32.75,43.77 31.37,44.39 29.83,44.39 C26.8,44.39 24.34,41.93 24.34,38.9 "
+ android:strokeWidth="2"
+ android:strokeAlpha="1"
+ android:strokeColor="@color/biometric_dialog_accent"
+ android:trimPathStart="0"
+ android:trimPathEnd="1"
+ android:trimPathOffset="0" />
+ <path
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:fillAlpha="1"
+ android:fillColor="@color/biometric_dialog_accent"
+ android:fillType="nonZero"
+ android:pathData=" M39 23.8 C39,25 39.9,25.9 41.1,25.9 C42.2,25.9 43.2,25 43.2,23.8 C43.2,22.6 42.3,21.7 41.1,21.7 C39.9,21.7 39,22.6 39,23.8c " />
+ <path
+ android:name="_R_G_L_0_G_D_3_P_0"
+ android:fillAlpha="1"
+ android:fillColor="@color/biometric_dialog_accent"
+ android:fillType="nonZero"
+ android:pathData=" M16.5 23.8 C16.5,25 17.4,25.9 18.6,25.9 C19.8,25.9 20.7,25 20.7,23.8 C20.7,22.6 19.8,21.7 18.6,21.7 C17.4,21.7 16.5,22.6 16.5,23.8c " />
+ <path
+ android:name="_R_G_L_0_G_D_4_P_0"
+ android:fillAlpha="1"
+ android:fillColor="@color/biometric_dialog_accent"
+ android:fillType="nonZero"
+ android:pathData=" M33.33 34.95 C33.33,34.95 28.13,34.95 28.13,34.95 C28.13,34.95 28.13,32.95 28.13,32.95 C28.13,32.95 31.33,32.95 31.33,32.95 C31.33,32.95 31.33,28.45 31.33,28.45 C31.33,28.45 33.33,28.45 33.33,28.45 C33.33,28.45 33.33,34.95 33.33,34.95c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_0_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="strokeAlpha"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_1_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="strokeAlpha"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_2_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_3_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_4_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="1.03"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="1.03"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="translateX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType" />
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/face_dialog_pulse_light_to_dark.xml b/packages/SystemUI/res/drawable/face_dialog_pulse_light_to_dark.xml
new file mode 100644
index 0000000..ab26408
--- /dev/null
+++ b/packages/SystemUI/res/drawable/face_dialog_pulse_light_to_dark.xml
@@ -0,0 +1,183 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector
+ android:width="60dp"
+ android:height="60dp"
+ android:viewportWidth="60"
+ android:viewportHeight="60">
+ <group android:name="_R_G">
+ <group
+ android:name="_R_G_L_0_G"
+ android:pivotX="30"
+ android:pivotY="30"
+ android:scaleX="1.03"
+ android:scaleY="1.03">
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
+ android:strokeWidth="2.5"
+ android:strokeAlpha="0.5"
+ android:strokeColor="@color/biometric_dialog_accent"
+ android:trimPathStart="0"
+ android:trimPathEnd="1"
+ android:trimPathOffset="0" />
+ <path
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:pathData=" M33.75 42.75 C32.75,43.77 31.37,44.39 29.83,44.39 C26.8,44.39 24.34,41.93 24.34,38.9 "
+ android:strokeWidth="2"
+ android:strokeAlpha="0.5"
+ android:strokeColor="@color/biometric_dialog_accent"
+ android:trimPathStart="0"
+ android:trimPathEnd="1"
+ android:trimPathOffset="0" />
+ <path
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:fillAlpha="0.5"
+ android:fillColor="@color/biometric_dialog_accent"
+ android:fillType="nonZero"
+ android:pathData=" M39 23.8 C39,25 39.9,25.9 41.1,25.9 C42.2,25.9 43.2,25 43.2,23.8 C43.2,22.6 42.3,21.7 41.1,21.7 C39.9,21.7 39,22.6 39,23.8c " />
+ <path
+ android:name="_R_G_L_0_G_D_3_P_0"
+ android:fillAlpha="0.5"
+ android:fillColor="@color/biometric_dialog_accent"
+ android:fillType="nonZero"
+ android:pathData=" M16.5 23.8 C16.5,25 17.4,25.9 18.6,25.9 C19.8,25.9 20.7,25 20.7,23.8 C20.7,22.6 19.8,21.7 18.6,21.7 C17.4,21.7 16.5,22.6 16.5,23.8c " />
+ <path
+ android:name="_R_G_L_0_G_D_4_P_0"
+ android:fillAlpha="0.5"
+ android:fillColor="@color/biometric_dialog_accent"
+ android:fillType="nonZero"
+ android:pathData=" M33.33 34.95 C33.33,34.95 28.13,34.95 28.13,34.95 C28.13,34.95 28.13,32.95 28.13,32.95 C28.13,32.95 31.33,32.95 31.33,32.95 C31.33,32.95 31.33,28.45 31.33,28.45 C31.33,28.45 33.33,28.45 33.33,28.45 C33.33,28.45 33.33,34.95 33.33,34.95c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_0_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="strokeAlpha"
+ android:startOffset="0"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_1_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="strokeAlpha"
+ android:startOffset="0"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_2_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_3_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_4_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="1.03"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="1.03"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.317,0 0.287,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="350"
+ android:propertyName="translateX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType" />
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/face_dialog_wink_from_dark.xml b/packages/SystemUI/res/drawable/face_dialog_wink_from_dark.xml
new file mode 100644
index 0000000..0cd542d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/face_dialog_wink_from_dark.xml
@@ -0,0 +1,208 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector
+ android:width="60dp"
+ android:height="60dp"
+ android:viewportWidth="60"
+ android:viewportHeight="60">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_1_G">
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
+ android:strokeWidth="2.5"
+ android:strokeAlpha="1"
+ android:strokeColor="@color/biometric_dialog_accent"
+ android:trimPathStart="0"
+ android:trimPathEnd="1"
+ android:trimPathOffset="0" />
+ </group>
+ <group
+ android:name="_R_G_L_0_G"
+ android:pivotX="30"
+ android:pivotY="30"
+ android:rotation="0"
+ android:scaleX="1"
+ android:scaleY="1">
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M33.75 42.75 C32.75,43.77 31.37,44.39 29.83,44.39 C26.8,44.39 24.34,41.93 24.34,38.9 "
+ android:strokeWidth="2"
+ android:strokeAlpha="1"
+ android:strokeColor="@color/biometric_dialog_accent"
+ android:trimPathStart="0"
+ android:trimPathEnd="1"
+ android:trimPathOffset="0" />
+ <path
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:fillAlpha="1"
+ android:fillColor="@color/biometric_dialog_accent"
+ android:fillType="nonZero"
+ android:pathData=" M39 23.8 C39,25 39.9,25.9 41.1,25.9 C42.2,25.9 43.2,25 43.2,23.8 C43.2,22.6 42.3,21.7 41.1,21.7 C39.9,21.7 39,22.6 39,23.8c " />
+ <group
+ android:name="_R_G_L_0_G_D_2_P_0_G_0_T_0"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="18.6"
+ android:translateY="23.8">
+ <path
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:fillAlpha="1"
+ android:fillColor="@color/biometric_dialog_accent"
+ android:fillType="nonZero"
+ android:pathData=" M-2.1 0 C-2.1,1.2 -1.2,2.1 0,2.1 C1.2,2.1 2.1,1.2 2.1,0 C2.1,-1.2 1.2,-2.1 0,-2.1 C-1.2,-2.1 -2.1,-1.2 -2.1,0c " />
+ </group>
+ <path
+ android:name="_R_G_L_0_G_D_3_P_0"
+ android:fillAlpha="1"
+ android:fillColor="@color/biometric_dialog_accent"
+ android:fillType="nonZero"
+ android:pathData=" M33.33 34.95 C33.33,34.95 28.13,34.95 28.13,34.95 C28.13,34.95 28.13,32.95 28.13,32.95 C28.13,32.95 31.33,32.95 31.33,32.95 C31.33,32.95 31.33,28.45 31.33,28.45 C31.33,28.45 33.33,28.45 33.33,28.45 C33.33,28.45 33.33,34.95 33.33,34.95c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_0_G_D_2_P_0_G_0_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="433"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="433"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.26"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleX"
+ android:startOffset="433"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleY"
+ android:startOffset="433"
+ android:valueFrom="0.26"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="433"
+ android:propertyName="rotation"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="-14"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="rotation"
+ android:startOffset="433"
+ android:valueFrom="-14"
+ android:valueTo="0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.305,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="433"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="1.06"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="433"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="1.06"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.2,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleX"
+ android:startOffset="433"
+ android:valueFrom="1.06"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.305,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleY"
+ android:startOffset="433"
+ android:valueFrom="1.06"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.305,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="1017"
+ android:propertyName="translateX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType" />
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml b/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml
index 8f411f4..33263a9 100644
--- a/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml
+++ b/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml
@@ -39,7 +39,7 @@
android:name="_R_G_L_1_G_D_0_P_0"
android:pathData=" M79.63 67.24 C79.63,67.24 111.5,47.42 147.83,67.24 "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
+ android:strokeColor="@color/biometric_dialog_accent"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="5.5"
@@ -50,7 +50,7 @@
android:name="_R_G_L_1_G_D_1_P_0"
android:pathData=" M64.27 98.07 C64.27,98.07 80.13,73.02 113.98,73.02 C147.83,73.02 163.56,97.26 163.56,97.26 "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
+ android:strokeColor="@color/biometric_dialog_accent"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="5.5"
@@ -61,7 +61,7 @@
android:name="_R_G_L_1_G_D_2_P_0"
android:pathData=" M72.53 151.07 C72.53,151.07 62.46,122.89 76.16,105.55 C89.86,88.21 106.72,86.73 113.98,86.73 C121.08,86.73 153.51,90.62 158.7,125.87 C159.14,128.82 158.8,132.88 157.18,136.09 C154.88,140.63 150.62,143.63 145.85,143.97 C133.78,144.85 129.76,137.92 129.26,128.49 C128.88,121.19 122.49,115.35 113.15,115.35 C102.91,115.35 95.97,126.69 99.77,139.74 C103.57,152.78 111.33,163.85 130.32,169.13 "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
+ android:strokeColor="@color/biometric_dialog_accent"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="5.5"
@@ -72,7 +72,7 @@
android:name="_R_G_L_1_G_D_3_P_0"
android:pathData=" M100.6 167.84 C100.6,167.84 82.76,152.1 83.75,130.31 C84.75,108.53 102.58,100.7 113.73,100.7 C124.87,100.7 144.19,108.56 144.19,130.01 "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
+ android:strokeColor="@color/biometric_dialog_accent"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="5.5"
@@ -83,7 +83,7 @@
android:name="_R_G_L_1_G_D_4_P_0"
android:pathData=" M113.73 129.17 C113.73,129.17 113.15,161.33 149.15,156.58 "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
+ android:strokeColor="@color/biometric_dialog_accent"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="5.5"
@@ -109,7 +109,7 @@
<path
android:name="_R_G_L_0_G_D_0_P_0"
android:fillAlpha="1"
- android:fillColor="?android:attr/colorError"
+ android:fillColor="@color/biometric_dialog_error"
android:fillType="nonZero"
android:pathData=" M-1.2 -1.25 C-1.2,-1.25 1.2,-1.25 1.2,-1.25 C1.2,-1.25 1.2,1.25 1.2,1.25 C1.2,1.25 -1.2,1.25 -1.2,1.25 C-1.2,1.25 -1.2,-1.25 -1.2,-1.25c " />
</group>
@@ -124,7 +124,7 @@
<path
android:name="_R_G_L_0_G_D_1_P_0"
android:fillAlpha="1"
- android:fillColor="?android:attr/colorError"
+ android:fillColor="@color/biometric_dialog_error"
android:fillType="nonZero"
android:pathData=" M-1.2 -7.5 C-1.2,-7.5 1.2,-7.5 1.2,-7.5 C1.2,-7.5 1.2,7.5 1.2,7.5 C1.2,7.5 -1.2,7.5 -1.2,7.5 C-1.2,7.5 -1.2,-7.5 -1.2,-7.5c " />
</group>
@@ -132,7 +132,7 @@
android:name="_R_G_L_0_G_D_2_P_0"
android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorError"
+ android:strokeColor="@color/biometric_dialog_error"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="2.5"
diff --git a/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml b/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml
index 89b8228..b899828 100644
--- a/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml
+++ b/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml
@@ -39,7 +39,7 @@
android:name="_R_G_L_1_G_D_0_P_0"
android:pathData=" M79.63 67.24 C79.63,67.24 111.5,47.42 147.83,67.24 "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
+ android:strokeColor="@color/biometric_dialog_accent"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="5.5"
@@ -50,7 +50,7 @@
android:name="_R_G_L_1_G_D_1_P_0"
android:pathData=" M64.27 98.07 C64.27,98.07 80.13,73.02 113.98,73.02 C147.83,73.02 163.56,97.26 163.56,97.26 "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
+ android:strokeColor="@color/biometric_dialog_accent"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="5.5"
@@ -61,7 +61,7 @@
android:name="_R_G_L_1_G_D_2_P_0"
android:pathData=" M72.53 151.07 C72.53,151.07 62.46,122.89 76.16,105.55 C89.86,88.21 106.72,86.73 113.98,86.73 C121.08,86.73 153.51,90.62 158.7,125.87 C159.14,128.82 158.8,132.88 157.18,136.09 C154.88,140.63 150.62,143.63 145.85,143.97 C133.78,144.85 129.76,137.92 129.26,128.49 C128.88,121.19 122.49,115.35 113.15,115.35 C102.91,115.35 95.97,126.69 99.77,139.74 C103.57,152.78 111.33,163.85 130.32,169.13 "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
+ android:strokeColor="@color/biometric_dialog_accent"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="5.5"
@@ -72,7 +72,7 @@
android:name="_R_G_L_1_G_D_3_P_0"
android:pathData=" M100.6 167.84 C100.6,167.84 82.76,152.1 83.75,130.31 C84.75,108.53 102.58,100.7 113.73,100.7 C124.87,100.7 144.19,108.56 144.19,130.01 "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
+ android:strokeColor="@color/biometric_dialog_accent"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="5.5"
@@ -83,7 +83,7 @@
android:name="_R_G_L_1_G_D_4_P_0"
android:pathData=" M113.73 129.17 C113.73,129.17 113.15,161.33 149.15,156.58 "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorAccent"
+ android:strokeColor="@color/biometric_dialog_accent"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="5.5"
@@ -109,7 +109,7 @@
<path
android:name="_R_G_L_0_G_D_0_P_0"
android:fillAlpha="1"
- android:fillColor="?android:attr/colorError"
+ android:fillColor="@color/biometric_dialog_error"
android:fillType="nonZero"
android:pathData=" M-1.2 -1.25 C-1.2,-1.25 1.2,-1.25 1.2,-1.25 C1.2,-1.25 1.2,1.25 1.2,1.25 C1.2,1.25 -1.2,1.25 -1.2,1.25 C-1.2,1.25 -1.2,-1.25 -1.2,-1.25c " />
</group>
@@ -124,7 +124,7 @@
<path
android:name="_R_G_L_0_G_D_1_P_0"
android:fillAlpha="1"
- android:fillColor="?android:attr/colorError"
+ android:fillColor="@color/biometric_dialog_error"
android:fillType="nonZero"
android:pathData=" M-1.2 -7.5 C-1.2,-7.5 1.2,-7.5 1.2,-7.5 C1.2,-7.5 1.2,7.5 1.2,7.5 C1.2,7.5 -1.2,7.5 -1.2,7.5 C-1.2,7.5 -1.2,-7.5 -1.2,-7.5c " />
</group>
@@ -132,7 +132,7 @@
android:name="_R_G_L_0_G_D_2_P_0"
android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
android:strokeAlpha="1"
- android:strokeColor="?android:attr/colorError"
+ android:strokeColor="@color/biometric_dialog_error"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="2.5"
diff --git a/packages/SystemUI/res/drawable/ic_arrow_back.xml b/packages/SystemUI/res/drawable/ic_arrow_back.xml
new file mode 100644
index 0000000..374f16b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_arrow_back.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,11H7.83l5.59-5.59L12,4l-8,8l8,8l1.41-1.41L7.83,13H20V11z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_bluetooth_transient.xml b/packages/SystemUI/res/drawable/ic_bluetooth_transient.xml
deleted file mode 100644
index 33d1fb3..0000000
--- a/packages/SystemUI/res/drawable/ic_bluetooth_transient.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="ic_bluetooth_transient"
- android:width="48dp"
- android:viewportWidth="48"
- android:height="48dp"
- android:viewportHeight="48" >
- <group
- android:name="ic_bluetooth_transient_0"
- android:translateX="23.99883"
- android:translateY="23.99839" >
- <group
- android:name="ic_bluetooth_transient_pivot"
- android:translateX="-23.99883"
- android:translateY="-23.99839" >
- <group
- android:name="ic_bluetooth_white_outlines"
- android:translateX="22.73986"
- android:translateY="23.99839" >
- <group
- android:name="ic_bluetooth_white_outlines_pivot"
- android:translateX="-12.84937"
- android:translateY="-20.4772" >
- <path
- android:name="b_shape_merged"
- android:pathData="M 17.1289978027,20.4790039062 c 0.0,0.0 7.5,-7.48100280762 7.5,-7.48100280762 c 0.81999206543,-0.819000244141 0.81999206543,-2.13899230957 0.0,-2.95999145508 c 0.0,0.0 -8.93899536133,-8.93899536133 -8.93899536133,-8.93899536133 c 0.0,0.0 -0.0610046386719,-0.0610046386719 -0.0610046386718,-0.0610046386719 c -0.844009399414,-0.788009643555 -2.16799926758,-0.74299621582 -2.95600891113,0.102005004883 c -0.359985351562,0.384994506836 -0.561996459961,0.891998291016 -0.56298828125,1.41899108887 c 0.0,0.0 0.0,12.8800048828 0.0,12.8800048828 c 0.0,0.0 -8.10000610352,-8.10000610352 -8.10000610352,-8.10000610352 c -0.81999206543,-0.81999206543 -2.12100219727,-0.81999206543 -2.9409942627,0.0 c -0.819000244141,0.819000244141 -0.819000244141,2.12001037598 0.0,2.94000244141 c 0.0,0.0 10.1799926758,10.1999969482 10.1799926758,10.1999969482 c 0.0,0.0 -10.1799926758,10.1790008545 -10.1799926758,10.1790008545 c -0.819000244141,0.820999145508 -0.819000244141,2.12100219727 0.0,2.94100952148 c 0.81999206543,0.81999206543 2.12100219727,0.81999206543 2.9409942627,0.0 c 0.0,0.0 8.10000610352,-8.1009979248 8.10000610352,-8.1009979248 c 0.0,0.0 0.0,12.9009857178 0.0,12.9009857178 c 0.0,1.14801025391 0.929992675781,2.08000183105 2.08000183105,2.08000183105 c 0.526992797852,0.0 1.03399658203,-0.199996948242 1.41999816895,-0.559997558594 c 0.0,0.0 0.0989990234375,-0.100006103516 0.0989990234375,-0.100006103516 c 0.0,0.0 8.91999816895,-8.91999816895 8.91999816895,-8.91999816895 c 0.81999206543,-0.820999145508 0.81999206543,-2.13999938965 0.0,-2.95999145508 c 0.0,0.0 -7.5,-7.46000671387 -7.5,-7.46000671387 Z M 16.0899963379,15.8190002441 c 0.0,0.0 0.0,-8.59999084473 0.0,-8.59999084473 c 0.0,0.0 4.30000305176,4.30000305176 4.30000305176,4.30000305176 c 0.0,0.0 -4.30000305176,4.29998779297 -4.30000305176,4.29998779297 Z M 16.0899963379,33.7190093994 c 0.0,0.0 0.0,-8.6009979248 0.0,-8.6009979248 c 0.0,0.0 4.30000305176,4.30099487305 4.30000305176,4.30099487305 c 0.0,0.0 -4.30000305176,4.30000305176 -4.30000305176,4.30000305176 Z"
- android:fillColor="#FFFFFFFF" />
- </group>
- </group>
- <group
- android:name="dot_left_outlines"
- android:translateX="20.6501"
- android:translateY="24.00011" >
- <group
- android:name="dot_left_outlines_pivot"
- android:translateX="-14.2"
- android:translateY="-3.55" >
- <path
- android:name="dot_left"
- android:pathData="M 5.66999816895,5.66999816895 c -1.18000793457,1.17999267578 -3.08000183105,1.17999267578 -4.24000549316,0.0 c -1.17999267578,-1.16000366211 -1.17999267578,-3.03999328613 -0.0199890136719,-4.2200012207 c 0.0,0.0 0.0199890136719,-0.0200042724609 0.0199890136719,-0.0200042724609 c 1.16000366211,-1.17999267578 3.04000854492,-1.17999267578 4.2200012207,-0.0199890136719 c 0.0,0.0 0.0200042724609,0.0199890136719 0.0200042724609,0.0199890136719 c 1.17999267578,1.17900085449 1.17999267578,3.06001281738 0.0,4.24000549316 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="0.5" />
- </group>
- </group>
- <group
- android:name="dot_right_outlines"
- android:translateX="27.3501"
- android:translateY="23.99741" >
- <group
- android:name="dot_right_outlines_pivot"
- android:translateX="7.1"
- android:translateY="-3.5525" >
- <path
- android:name="dot_right"
- android:pathData="M 5.66999816895,1.43499755859 c 1.17999267578,1.18000793457 1.17999267578,3.08000183105 0.0,4.24000549316 c -1.18000793457,1.17999267578 -3.08000183105,1.17999267578 -4.24000549316,0.0 c -1.17999267578,-1.16000366211 -1.17999267578,-3.04000854492 -0.0200042724609,-4.21899414062 c 0.0,0.0 0.0200042724609,-0.0210113525391 0.0200042724609,-0.0210113525391 c 1.15299987793,-1.17098999023 3.03799438477,-1.18499755859 4.20899963379,-0.0309906005859 c 0.0,0.0 0.031005859375,0.0309906005859 0.031005859375,0.0309906005859 Z"
- android:fillColor="#FFFFFFFF" />
- </group>
- </group>
- </group>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_bluetooth_transient_animation.xml b/packages/SystemUI/res/drawable/ic_bluetooth_transient_animation.xml
deleted file mode 100644
index dc3c3e2..0000000
--- a/packages/SystemUI/res/drawable/ic_bluetooth_transient_animation.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<animated-vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:drawable="@drawable/ic_bluetooth_transient" >
- <target
- android:name="dot_left"
- android:animation="@anim/ic_bluetooth_transient_dot_left_animation" />
- <target
- android:name="dot_right"
- android:animation="@anim/ic_bluetooth_transient_dot_right_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_cast.xml b/packages/SystemUI/res/drawable/ic_cast.xml
index a2c2eb2..fe1d99f 100644
--- a/packages/SystemUI/res/drawable/ic_cast.xml
+++ b/packages/SystemUI/res/drawable/ic_cast.xml
@@ -14,8 +14,8 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="17dp"
+ android:height="17dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/packages/SystemUI/res/drawable/ic_cast_connected.xml b/packages/SystemUI/res/drawable/ic_cast_connected.xml
index 995fd49..aa4c152 100644
--- a/packages/SystemUI/res/drawable/ic_cast_connected.xml
+++ b/packages/SystemUI/res/drawable/ic_cast_connected.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="17dp"
- android:height="17dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FFFFFFFF"
+ android:fillColor="@android:color/white"
android:pathData="M1,18v3h3C4,19.34 2.66,18 1,18zM1,14v2c2.76,0 5,2.24 5,5h2C8,17.13 4.87,14 1,14zM19,7H5v1.63c3.96,1.28 7.09,4.41 8.37,8.37H19V7zM1,10v2c4.97,0 9,4.03 9,9h2C12,14.92 7.07,10 1,10zM21,3H3C1.9,3 1,3.9 1,5v3h2V5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2V5C23,3.9 22.1,3 21,3"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/packages/SystemUI/res/drawable/ic_cast_connected_fill.xml
similarity index 62%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to packages/SystemUI/res/drawable/ic_cast_connected_fill.xml
index 8b8258f..61d524d 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/packages/SystemUI/res/drawable/ic_cast_connected_fill.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2019 The Android Open Source Project
~
@@ -15,12 +14,13 @@
~ limitations under the License
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="17dp"
+ android:height="17dp"
+ android:tint="?android:attr/colorError"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,7H5v1.63c3.96,1.28 7.09,4.41 8.37,8.37H19V7z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_transient.xml b/packages/SystemUI/res/drawable/ic_hotspot_transient.xml
deleted file mode 100644
index 22f7267..0000000
--- a/packages/SystemUI/res/drawable/ic_hotspot_transient.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="ic_hotspot_transient"
- android:width="48dp"
- android:viewportWidth="48"
- android:height="48dp"
- android:viewportHeight="48" >
- <group
- android:name="ic_hotspot_transient_0"
- android:translateX="24.00209"
- android:translateY="24.2354" >
- <group
- android:name="ic_hotspot_transient_pivot"
- android:translateX="-24.00209"
- android:translateY="-24.2354" >
- <group
- android:name="circle01"
- android:translateX="24.0002"
- android:translateY="25.9996" >
- <group
- android:name="circle01_pivot"
- android:translateX="-24.0002"
- android:translateY="-25.9996" >
- <path
- android:name="circle01_0"
- android:pathData="M 24.0001983643,21.9996032715 c -2.19999694824,0.0 -4.0,1.80000305176 -4.0,4.0 c 0.0,2.20100402832 1.80000305176,4.0 4.0,4.0 c 2.19999694824,0.0 4.0,-1.79899597168 4.0,-4.0 c 0.0,-2.19999694824 -1.80000305176,-4.0 -4.0,-4.0 Z"
- android:fillColor="#FFFFFFFF" />
- </group>
- </group>
- <group
- android:name="circle02"
- android:translateX="24.00071"
- android:translateY="24.74686" >
- <group
- android:name="circle02_pivot"
- android:translateX="-24.00071"
- android:translateY="-24.74686" >
- <path
- android:name="circle02_0"
- android:pathData="M 36.0001983643,25.9996032715 c -0.00299072265625,-6.62699890137 -5.37899780273,-11.9969940186 -12.0059967041,-11.9940032959 c -0.5,0.0 -0.999008178711,0.031005859375 -1.4940032959,0.0940093994141 c -5.24000549316,0.640991210938 -9.55999755859,4.81999206543 -10.3600006104,10.0399932861 c -0.639999389648,4.2799987793 0.979995727539,8.22099304199 3.83999633789,10.7799987793 c 0.960006713867,0.86100769043 2.48001098633,0.660003662109 3.1190032959,-0.460006713867 c 0.481002807617,-0.839996337891 0.281005859375,-1.87998962402 -0.438995361328,-2.51899719238 c -2.21299743652,-1.97099304199 -3.15200805664,-5.00500488281 -2.44000244141,-7.8809967041 c 0.695007324219,-2.86999511719 2.93099975586,-5.11500549316 5.79899597168,-5.81900024414 c 4.29100036621,-1.08599853516 8.65000915527,1.51100158691 9.73600769043,5.80200195312 c 0.162002563477,0.639999389648 0.244003295898,1.29699707031 0.244995117188,1.95700073242 c 0.0,2.36099243164 -1.02000427246,4.45999145508 -2.66000366211,5.91999816895 c -0.720001220703,0.660003662109 -0.939987182617,1.69999694824 -0.459991455078,2.53999328613 c 0.619995117188,1.08000183105 2.08000183105,1.38000488281 3.0,0.560012817383 c 2.61599731445,-2.26699829102 4.1190032959,-5.55801391602 4.11999511719,-9.02000427246 Z"
- android:fillColor="#FFFFFFFF" />
- </group>
- </group>
- <group
- android:name="circle03"
- android:translateX="24.00209"
- android:translateY="24.23539" >
- <group
- android:name="circle03_pivot"
- android:translateX="-24.00209"
- android:translateY="-24.23539" >
- <path
- android:name="circle03_0"
- android:pathData="M 21.6602020264,6.13960266113 c -9.24000549316,1.03999328613 -16.6999969482,8.66000366211 -17.5599975586,17.9199981689 c -0.690002441406,7.00500488281 2.36599731445,13.8540039062 8.03999328613,18.0200042725 c 0.958999633789,0.700988769531 2.32000732422,0.401000976562 2.91900634766,-0.620010375977 c 0.5,-0.860000610352 0.280990600586,-1.97898864746 -0.518997192383,-2.57998657227 c -4.56001281738,-3.38000488281 -7.30000305176,-9.09901428223 -6.32000732422,-15.3990020752 c 1.08000183105,-7.0 6.91900634766,-12.5800018311 13.9600067139,-13.3610076904 c 9.63999938965,-1.09999084473 17.8199920654,6.44000244141 17.8199920654,15.8800048828 c 0.0,5.30000305176 -2.57998657227,9.95999145508 -6.53999328613,12.8800048828 c -0.800003051758,0.600997924805 -1.02000427246,1.69999694824 -0.520004272461,2.57998657227 c 0.600006103516,1.04000854492 1.96000671387,1.32099914551 2.91999816895,0.620010375977 c 5.12100219727,-3.75500488281 8.14500427246,-9.72799682617 8.13999938965,-16.0800018311 c 0.0,-11.8200073242 -10.2599945068,-21.2400054932 -22.3399963379,-19.8600006104 Z"
- android:fillColor="#FFFFFFFF" />
- </group>
- </group>
- </group>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_transient_animation.xml b/packages/SystemUI/res/drawable/ic_hotspot_transient_animation.xml
deleted file mode 100644
index 929a941..0000000
--- a/packages/SystemUI/res/drawable/ic_hotspot_transient_animation.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<animated-vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:drawable="@drawable/ic_hotspot_transient" >
- <target
- android:name="circle01_0"
- android:animation="@anim/ic_hotspot_transient_circle_1_animation" />
- <target
- android:name="circle02_0"
- android:animation="@anim/ic_hotspot_transient_circle_2_animation" />
- <target
- android:name="circle03_0"
- android:animation="@anim/ic_hotspot_transient_circle_3_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_wifi_transient.xml b/packages/SystemUI/res/drawable/ic_signal_wifi_transient.xml
deleted file mode 100644
index 880e1bb..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_wifi_transient.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="ic_signal_wifi_transient"
- android:width="48dp"
- android:viewportWidth="48"
- android:height="48dp"
- android:viewportHeight="48" >
- <group
- android:name="ic_signal_wifi_4_bar_48px_2"
- android:translateX="24.25"
- android:translateY="25.73401" >
- <group
- android:name="ic_signal_wifi_4_bar_48px_2_pivot"
- android:translateX="-23.21545"
- android:translateY="-18.86649" >
- <group
- android:name="wifi_2"
- android:translateX="23.481"
- android:translateY="18.71151" >
- <path
- android:name="wifi"
- android:pathData="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="0.5" />
- </group>
- <group
- android:name="wifi_0"
- android:translateX="23.481"
- android:translateY="18.71151" >
- <path
- android:name="wifi_1"
- android:pathData="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="0" />
- </group>
- </group>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_wifi_transient_animation.xml b/packages/SystemUI/res/drawable/ic_signal_wifi_transient_animation.xml
deleted file mode 100644
index 9f5aaeb..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_wifi_transient_animation.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<animated-vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:drawable="@drawable/ic_signal_wifi_transient" >
- <target
- android:name="wifi_1"
- android:animation="@anim/ic_signal_wifi_transient_wifi_1_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_menu.xml b/packages/SystemUI/res/drawable/ic_sysbar_menu.xml
deleted file mode 100644
index d53c95b..0000000
--- a/packages/SystemUI/res/drawable/ic_sysbar_menu.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="21dp"
- android:height="21dp"
- android:viewportWidth="28"
- android:viewportHeight="28">
-
- <path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M14,9.5c1.24,0,2.25-1.01,2.25-2.25S15.24,5,14,5s-2.25,1.01-2.25,2.25S12.76,9.5,14,9.5z M14,11.75 c-1.24,0-2.25,1.01-2.25,2.25s1.01,2.25,2.25,2.25s2.25-1.01,2.25-2.25S15.24,11.75,14,11.75z M14,18.5 c-1.24,0-2.25,1.01-2.25,2.25S12.76,23,14,23s2.25-1.01,2.25-2.25S15.24,18.5,14,18.5z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_collapse.xml b/packages/SystemUI/res/drawable/ic_volume_collapse.xml
deleted file mode 100644
index 3853d12..0000000
--- a/packages/SystemUI/res/drawable/ic_volume_collapse.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="ic_caret_down"
- android:width="24dp"
- android:viewportWidth="24"
- android:height="24dp"
- android:viewportHeight="24"
- android:tint="?android:attr/colorControlNormal" >
- <group
- android:name="caret___4" >
- <group
- android:name="right"
- android:translateX="11.287"
- android:translateY="8.701"
- android:rotation="45" >
- <group
- android:name="right_pivot"
- android:translateX="4.242" >
- <path
- android:name="rectangle_path_1"
- android:fillColor="#FFFFFFFF"
- android:pathData="M -3.242,-1.0 l 6.484,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l -6.484,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z" />
- </group>
- </group>
- <group
- android:name="left"
- android:translateX="12.699"
- android:translateY="8.701"
- android:rotation="-45" >
- <group
- android:name="left_pivot"
- android:translateX="-4.242" >
- <path
- android:name="rectangle_path_2"
- android:fillColor="#FFFFFFFF"
- android:pathData="M -3.242,-1.0 l 6.484,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l -6.484,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z" />
- </group>
- </group>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_collapse_animation.xml b/packages/SystemUI/res/drawable/ic_volume_collapse_animation.xml
index 18c6307..101a0c8 100644
--- a/packages/SystemUI/res/drawable/ic_volume_collapse_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_collapse_animation.xml
@@ -13,13 +13,223 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<animated-vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:drawable="@drawable/ic_volume_collapse" >
- <target
- android:name="right"
- android:animation="@anim/ic_caret_down_right_animation" />
- <target
- android:name="left"
- android:animation="@anim/ic_caret_down_left_animation" />
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector android:height="24dp" android:width="24dp" android:viewportHeight="24"
+ android:viewportWidth="24">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="12"
+ android:translateY="12">
+ <group android:name="_R_G_L_1_G_T_1" android:translateX="-0.004"
+ android:translateY="-3.608" android:rotation="0">
+ <group android:name="_R_G_L_1_G" android:translateX="-0.246"
+ android:translateY="-1.642">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M6.84 9.66 C6.84,9.66 8.25,8.25 8.25,8.25 C8.25,8.25 0.25,0.25 0.25,0.25 C0.25,0.25 -1.12,1.71 -1.12,1.71 C-1.12,1.71 6.84,9.66 6.84,9.66c "/>
+ </group>
+ </group>
+ </group>
+ <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12"
+ android:translateY="12">
+ <group android:name="_R_G_L_0_G_T_1" android:translateX="0"
+ android:translateY="-3.585" android:rotation="0">
+ <group android:name="_R_G_L_0_G" android:translateX="-8.25"
+ android:translateY="-1.665">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 8.25,0.25 8.25,0.25 C8.25,0.25 9.64,1.69 9.64,1.69 C9.64,1.69 1.66,9.66 1.66,9.66c "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_1_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="pathData" android:duration="50"
+ android:startOffset="0"
+ android:valueFrom="M6.84 9.66 C6.84,9.66 8.25,8.25 8.25,8.25 C8.25,8.25 0.25,0.25 0.25,0.25 C0.25,0.25 -1.12,1.71 -1.12,1.71 C-1.12,1.71 6.84,9.66 6.84,9.66c "
+ android:valueTo="M6.84 9.66 C6.84,9.66 8.25,8.25 8.25,8.25 C8.25,8.25 0.96,0.9 0.96,0.9 C0.96,0.9 -1.12,1.71 -1.12,1.71 C-1.12,1.71 6.84,9.66 6.84,9.66c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="33"
+ android:startOffset="50"
+ android:valueFrom="M6.84 9.66 C6.84,9.66 8.25,8.25 8.25,8.25 C8.25,8.25 0.96,0.9 0.96,0.9 C0.96,0.9 -1.12,1.71 -1.12,1.71 C-1.12,1.71 6.84,9.66 6.84,9.66c "
+ android:valueTo="M6.84 9.66 C6.84,9.66 8.25,8.25 8.25,8.25 C8.25,8.25 0.96,0.9 0.96,0.9 C0.96,0.9 -0.55,2.35 -0.55,2.35 C-0.55,2.35 6.84,9.66 6.84,9.66c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="83"
+ android:valueFrom="M6.84 9.66 C6.84,9.66 8.25,8.25 8.25,8.25 C8.25,8.25 0.96,0.9 0.96,0.9 C0.96,0.9 -0.55,2.35 -0.55,2.35 C-0.55,2.35 6.84,9.66 6.84,9.66c "
+ android:valueTo="M6.84 9.66 C6.84,9.66 8.25,8.25 8.25,8.25 C8.25,8.25 0.25,0.25 0.25,0.25 C0.25,0.25 -0.87,2.12 -0.87,2.12 C-0.87,2.12 6.84,9.66 6.84,9.66c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="33"
+ android:startOffset="100"
+ android:valueFrom="M6.84 9.66 C6.84,9.66 8.25,8.25 8.25,8.25 C8.25,8.25 0.25,0.25 0.25,0.25 C0.25,0.25 -0.87,2.12 -0.87,2.12 C-0.87,2.12 6.84,9.66 6.84,9.66c "
+ android:valueTo="M6.84 9.66 C6.84,9.66 8.25,8.25 8.25,8.25 C8.25,8.25 0.25,0.25 0.25,0.25 C0.25,0.25 -1.05,1.92 -1.05,1.92 C-1.05,1.92 6.84,9.66 6.84,9.66c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="133"
+ android:valueFrom="M6.84 9.66 C6.84,9.66 8.25,8.25 8.25,8.25 C8.25,8.25 0.25,0.25 0.25,0.25 C0.25,0.25 -1.05,1.92 -1.05,1.92 C-1.05,1.92 6.84,9.66 6.84,9.66c "
+ android:valueTo="M6.84 9.66 C6.84,9.66 8.25,8.25 8.25,8.25 C8.25,8.25 0.25,0.25 0.25,0.25 C0.25,0.25 -1.12,1.71 -1.12,1.71 C-1.12,1.71 6.84,9.66 6.84,9.66c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="250"
+ android:startOffset="0" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M -0.004,-3.608C -0.004,-2.39758332538605 -0.004,2.44358332538605 -0.004,3.654">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="rotation" android:duration="200"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="-90"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="pathData" android:duration="50"
+ android:startOffset="0"
+ android:valueFrom="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 8.25,0.25 8.25,0.25 C8.25,0.25 9.64,1.69 9.64,1.69 C9.64,1.69 1.66,9.66 1.66,9.66c "
+ android:valueTo="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 8.2,0.59 8.2,0.59 C8.2,0.59 9.84,1.88 9.84,1.88 C9.84,1.88 1.66,9.66 1.66,9.66c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="50"
+ android:valueFrom="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 8.2,0.59 8.2,0.59 C8.2,0.59 9.84,1.88 9.84,1.88 C9.84,1.88 1.66,9.66 1.66,9.66c "
+ android:valueTo="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 8.25,0.25 8.25,0.25 C8.25,0.25 9.64,1.69 9.64,1.69 C9.64,1.69 1.66,9.66 1.66,9.66c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="67"
+ android:valueFrom="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 8.25,0.25 8.25,0.25 C8.25,0.25 9.64,1.69 9.64,1.69 C9.64,1.69 1.66,9.66 1.66,9.66c "
+ android:valueTo="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 7.45,0.93 7.45,0.93 C7.45,0.93 9.23,2.03 9.23,2.03 C9.23,2.03 1.66,9.66 1.66,9.66c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="83"
+ android:valueFrom="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 7.45,0.93 7.45,0.93 C7.45,0.93 9.23,2.03 9.23,2.03 C9.23,2.03 1.66,9.66 1.66,9.66c "
+ android:valueTo="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 8.25,0.25 8.25,0.25 C8.25,0.25 9.37,1.99 9.37,1.99 C9.37,1.99 1.66,9.66 1.66,9.66c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="33"
+ android:startOffset="100"
+ android:valueFrom="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 8.25,0.25 8.25,0.25 C8.25,0.25 9.37,1.99 9.37,1.99 C9.37,1.99 1.66,9.66 1.66,9.66c "
+ android:valueTo="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 8.25,0.25 8.25,0.25 C8.25,0.25 9.64,1.69 9.64,1.69 C9.64,1.69 1.66,9.66 1.66,9.66c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="133"
+ android:valueFrom="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 8.25,0.25 8.25,0.25 C8.25,0.25 9.64,1.69 9.64,1.69 C9.64,1.69 1.66,9.66 1.66,9.66c "
+ android:valueTo="M1.66 9.66 C1.66,9.66 0.25,8.25 0.25,8.25 C0.25,8.25 8.25,0.25 8.25,0.25 C8.25,0.25 9.64,1.69 9.64,1.69 C9.64,1.69 1.66,9.66 1.66,9.66c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="250"
+ android:startOffset="0" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,-3.585C 0,-2.3787500476837202 0,2.4457500476837204 0,3.652">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="rotation" android:duration="200"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="90"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="267"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_expand.xml b/packages/SystemUI/res/drawable/ic_volume_expand.xml
deleted file mode 100644
index 79ff808..0000000
--- a/packages/SystemUI/res/drawable/ic_volume_expand.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="ic_caret_up"
- android:width="24dp"
- android:viewportWidth="24"
- android:height="24dp"
- android:viewportHeight="24"
- android:tint="?android:attr/colorControlNormal" >
- <group
- android:name="caret___4" >
- <group
- android:name="right"
- android:translateX="11.287"
- android:translateY="15.287"
- android:rotation="-45" >
- <group
- android:name="right_pivot"
- android:translateX="4.242" >
- <path
- android:name="rectangle_path_1"
- android:fillColor="#FFFFFFFF"
- android:pathData="M -3.242,-1.0 l 6.484,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l -6.484,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z" />
- </group>
- </group>
- <group
- android:name="left"
- android:translateX="12.699"
- android:translateY="15.287"
- android:rotation="45" >
- <group
- android:name="left_pivot"
- android:translateX="-4.242" >
- <path
- android:name="rectangle_path_2"
- android:fillColor="#FFFFFFFF"
- android:pathData="M -3.242,-1.0 l 6.484,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l -6.484,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z" />
- </group>
- </group>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_expand_animation.xml b/packages/SystemUI/res/drawable/ic_volume_expand_animation.xml
index abd6678..152d26c 100644
--- a/packages/SystemUI/res/drawable/ic_volume_expand_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_expand_animation.xml
@@ -13,13 +13,233 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<animated-vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:drawable="@drawable/ic_volume_expand" >
- <target
- android:name="right"
- android:animation="@anim/ic_caret_up_right_animation" />
- <target
- android:name="left"
- android:animation="@anim/ic_caret_up_left_animation" />
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector android:height="24dp" android:width="24dp" android:viewportHeight="24"
+ android:viewportWidth="24">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="12"
+ android:translateY="12">
+ <group android:name="_R_G_L_1_G_T_1" android:translateX="0"
+ android:translateY="3.439" android:rotation="0">
+ <group android:name="_R_G_L_1_G" android:translateX="-8.25"
+ android:translateY="-8.1">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 8.25,9.66 8.25,9.66 C8.25,9.66 8.25,6.83 8.25,6.83 C8.25,6.83 1.66,0.25 1.66,0.25c "/>
+ </group>
+ </group>
+ </group>
+ <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="12"
+ android:translateY="12">
+ <group android:name="_R_G_L_0_G_T_1" android:translateX="0"
+ android:translateY="3.439" android:rotation="0">
+ <group android:name="_R_G_L_0_G" android:translateX="-0.25"
+ android:translateY="-8.1">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.25,9.66 0.25,9.66 C0.25,9.66 0.25,6.83 0.25,6.83 C0.25,6.83 6.84,0.25 6.84,0.25c "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_1_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="pathData" android:duration="33"
+ android:startOffset="0"
+ android:valueFrom="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 8.25,9.66 8.25,9.66 C8.25,9.66 8.25,6.83 8.25,6.83 C8.25,6.83 1.66,0.25 1.66,0.25c "
+ android:valueTo="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 7.97,9.5 7.97,9.5 C7.97,9.5 8.59,7.15 8.59,7.15 C8.59,7.15 1.66,0.25 1.66,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="33"
+ android:valueFrom="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 7.97,9.5 7.97,9.5 C7.97,9.5 8.59,7.15 8.59,7.15 C8.59,7.15 1.66,0.25 1.66,0.25c "
+ android:valueTo="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 7.71,9.4 7.71,9.4 C7.71,9.4 8.59,7.15 8.59,7.15 C8.59,7.15 1.66,0.25 1.66,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="50"
+ android:valueFrom="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 7.71,9.4 7.71,9.4 C7.71,9.4 8.59,7.15 8.59,7.15 C8.59,7.15 1.66,0.25 1.66,0.25c "
+ android:valueTo="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 7.43,9.08 7.43,9.08 C7.43,9.08 8.87,7.47 8.87,7.47 C8.87,7.47 1.66,0.25 1.66,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="67"
+ android:valueFrom="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 7.43,9.08 7.43,9.08 C7.43,9.08 8.87,7.47 8.87,7.47 C8.87,7.47 1.66,0.25 1.66,0.25c "
+ android:valueTo="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 7.43,9.08 7.43,9.08 C7.43,9.08 9,7.68 9,7.68 C9,7.68 1.66,0.25 1.66,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="83"
+ android:valueFrom="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 7.43,9.08 7.43,9.08 C7.43,9.08 9,7.68 9,7.68 C9,7.68 1.66,0.25 1.66,0.25c "
+ android:valueTo="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 7.43,9.08 7.43,9.08 C7.43,9.08 9.08,7.81 9.08,7.81 C9.08,7.81 1.66,0.25 1.66,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="50"
+ android:startOffset="100"
+ android:valueFrom="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 7.43,9.08 7.43,9.08 C7.43,9.08 9.08,7.81 9.08,7.81 C9.08,7.81 1.66,0.25 1.66,0.25c "
+ android:valueTo="M1.66 0.25 C1.66,0.25 0.25,1.66 0.25,1.66 C0.25,1.66 7.95,9.61 7.95,9.61 C7.95,9.61 9.58,8.01 9.58,8.01 C9.58,8.01 1.66,0.25 1.66,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="250"
+ android:startOffset="0" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,3.439C 0,2.24316667461395 0,-2.54016667461395 0,-3.736">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="rotation" android:duration="200"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="-90"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="0"
+ android:valueFrom="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.24,9.63 0.24,9.63 C0.24,9.63 -0.15,7.2 -0.15,7.2 C-0.15,7.2 6.84,0.25 6.84,0.25c "
+ android:valueTo="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.22,9.59 0.22,9.59 C0.22,9.59 -0.4,7.45 -0.4,7.45 C-0.4,7.45 6.84,0.25 6.84,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="17"
+ android:valueFrom="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.22,9.59 0.22,9.59 C0.22,9.59 -0.4,7.45 -0.4,7.45 C-0.4,7.45 6.84,0.25 6.84,0.25c "
+ android:valueTo="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.36,9.46 0.36,9.46 C0.36,9.46 -0.44,7.6 -0.44,7.6 C-0.44,7.6 6.84,0.25 6.84,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="33"
+ android:valueFrom="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.36,9.46 0.36,9.46 C0.36,9.46 -0.44,7.6 -0.44,7.6 C-0.44,7.6 6.84,0.25 6.84,0.25c "
+ android:valueTo="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.71,9.4 0.71,9.4 C0.71,9.4 -0.61,7.63 -0.61,7.63 C-0.61,7.63 6.84,0.25 6.84,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="33"
+ android:startOffset="50"
+ android:valueFrom="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.71,9.4 0.71,9.4 C0.71,9.4 -0.61,7.63 -0.61,7.63 C-0.61,7.63 6.84,0.25 6.84,0.25c "
+ android:valueTo="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.93,9.29 0.93,9.29 C0.93,9.29 -0.5,7.69 -0.5,7.69 C-0.5,7.69 6.84,0.25 6.84,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="17"
+ android:startOffset="83"
+ android:valueFrom="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.93,9.29 0.93,9.29 C0.93,9.29 -0.5,7.69 -0.5,7.69 C-0.5,7.69 6.84,0.25 6.84,0.25c "
+ android:valueTo="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.84,9.33 0.84,9.33 C0.84,9.33 -0.53,7.8 -0.53,7.8 C-0.53,7.8 6.84,0.25 6.84,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="117"
+ android:startOffset="100"
+ android:valueFrom="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.84,9.33 0.84,9.33 C0.84,9.33 -0.53,7.8 -0.53,7.8 C-0.53,7.8 6.84,0.25 6.84,0.25c "
+ android:valueTo="M6.84 0.25 C6.84,0.25 8.25,1.66 8.25,1.66 C8.25,1.66 0.56,9.63 0.56,9.63 C0.56,9.63 -1.08,8.07 -1.08,8.07 C-1.08,8.07 6.84,0.25 6.84,0.25c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="250"
+ android:startOffset="0" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,3.439C 0,2.24316667461395 0,-2.54016667461395 0,-3.736">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="rotation" android:duration="200"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="90"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="267"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
</animated-vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_cast.xml b/packages/SystemUI/res/drawable/stat_sys_cast.xml
index de7ec9d..6186ead 100644
--- a/packages/SystemUI/res/drawable/stat_sys_cast.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_cast.xml
@@ -13,7 +13,4 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetLeft="2.5dp"
- android:insetRight="2.5dp"
- android:drawable="@drawable/ic_cast_connected" />
\ No newline at end of file
+<com.android.systemui.statusbar.CastDrawable />
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml b/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
index e38b482..3761a40 100644
--- a/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
@@ -1,12 +1,27 @@
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="23dp"
- android:height="18dp"
- android:viewportWidth="23.0"
- android:viewportHeight="18.0">
- <!--
- The asset contains a briefcase symbol of 14.551dp x 13.824dp in the center.
- -->
+ android:width="17dp"
+ android:height="17dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
<path
- android:pathData="M17.32,5.06h-2.91V3.6c0,-0.81 -0.65,-1.46 -1.46,-1.46h-2.91c-0.81,0 -1.46,0.65 -1.46,1.46v1.46H5.68c-0.81,0 -1.45,0.65 -1.45,1.46l-0.01,8c0,0.81 0.65,1.46 1.46,1.46h11.64c0.81,0 1.46,-0.65 1.46,-1.46v-8C18.78,5.7 18.13,5.06 17.32,5.06zM11.5,11.6c-0.8,0 -1.46,-0.65 -1.46,-1.46c0,-0.8 0.65,-1.46 1.46,-1.46s1.46,0.65 1.46,1.46C12.96,10.95 12.3,11.6 11.5,11.6zM12.96,5.06h-2.91V3.6h2.91V5.06z"
- android:fillColor="#FF000000"/>
-</vector>
+ android:fillColor="@android:color/white"
+ android:pathData="M20,6h-4V4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8 C22,6.9,21.1,6,20,6z M10,4h4v2h-4V4z M20,19H4V8h16V19z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 12 C 12.8284271247 12 13.5 12.6715728753 13.5 13.5 C 13.5 14.3284271247 12.8284271247 15 12 15 C 11.1715728753 15 10.5 14.3284271247 10.5 13.5 C 10.5 12.6715728753 11.1715728753 12 12 12 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/status_bar_notification_section_header_clear_btn.xml b/packages/SystemUI/res/drawable/status_bar_notification_section_header_clear_btn.xml
new file mode 100644
index 0000000..15f14d8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/status_bar_notification_section_header_clear_btn.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="40dp"
+ android:height="40dp"
+ android:viewportWidth="40"
+ android:viewportHeight="40">
+ <path
+ android:fillColor="#5F6368"
+ android:pathData="M24.6667 16.2733L23.7267 15.3333L20 19.06L16.2734 15.3333L15.3334 16.2733L19.06 20L15.3334 23.7267L16.2734 24.6667L20 20.94L23.7267 24.6667L24.6667 23.7267L20.94 20L24.6667 16.2733Z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml
index c452855..c560d7e 100644
--- a/packages/SystemUI/res/layout/biometric_dialog.xml
+++ b/packages/SystemUI/res/layout/biometric_dialog.xml
@@ -37,7 +37,8 @@
android:id="@+id/space"
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_weight="1" />
+ android:layout_weight="1"
+ android:contentDescription="@string/biometric_dialog_empty_space_description"/>
<ScrollView
android:layout_width="match_parent"
@@ -119,7 +120,7 @@
android:textSize="12sp"
android:gravity="center_horizontal"
android:accessibilityLiveRegion="polite"
- android:textColor="?android:attr/textColorSecondary"/>
+ android:textColor="@color/biometric_dialog_gray"/>
<LinearLayout
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/bubble_dismiss_target.xml b/packages/SystemUI/res/layout/bubble_dismiss_target.xml
new file mode 100644
index 0000000..245177c
--- /dev/null
+++ b/packages/SystemUI/res/layout/bubble_dismiss_target.xml
@@ -0,0 +1,66 @@
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+<!-- Bubble dismiss target consisting of an X icon and the text 'Dismiss'. -->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/pip_dismiss_gradient_height"
+ android:layout_gravity="bottom|center_horizontal">
+
+ <LinearLayout
+ android:id="@+id/bubble_dismiss_icon_container"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:paddingBottom="@dimen/bubble_dismiss_target_padding_y"
+ android:paddingTop="@dimen/bubble_dismiss_target_padding_y"
+ android:paddingLeft="@dimen/bubble_dismiss_target_padding_x"
+ android:paddingRight="@dimen/bubble_dismiss_target_padding_x"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/bubble_dismiss_close_icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:src="@drawable/bubble_dismiss_icon" />
+
+ <TextView
+ android:id="@+id/bubble_dismiss_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="9dp"
+ android:layout_marginBottom="9dp"
+ android:layout_marginLeft="8dp"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"
+ android:textColor="@android:color/white"
+ android:shadowColor="@android:color/black"
+ android:shadowDx="-1"
+ android:shadowDy="1"
+ android:shadowRadius="0.01"
+ android:text="@string/bubble_dismiss_text" />
+
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/bubble_dismiss_circle"
+ android:layout_width="@dimen/bubble_dismiss_encircle_size"
+ android:layout_height="@dimen/bubble_dismiss_encircle_size"
+ android:layout_gravity="center"
+ android:alpha="0"
+ android:background="@drawable/bubble_dismiss_circle" />
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/bubble_expanded_view.xml b/packages/SystemUI/res/layout/bubble_expanded_view.xml
index b734125..5b93edd 100644
--- a/packages/SystemUI/res/layout/bubble_expanded_view.xml
+++ b/packages/SystemUI/res/layout/bubble_expanded_view.xml
@@ -27,35 +27,14 @@
android:layout_height="@dimen/bubble_pointer_height"
/>
- <FrameLayout
- android:id="@+id/permission_or_settings"
- android:layout_width="match_parent"
+ <com.android.systemui.statusbar.AlphaOptimizedButton
+ style="@android:style/Widget.Material.Button.Borderless"
+ android:id="@+id/settings_button"
+ android:layout_gravity="end"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:animateLayoutChanges="true">
-
- <com.android.systemui.statusbar.AlphaOptimizedButton
- style="@android:style/Widget.Material.Button.Borderless"
- android:id="@+id/settings_button"
- android:layout_gravity="end"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:text="@string/manage_bubbles_text"
- android:textColor="?attr/wallpaperTextColor"/>
-
- <include layout="@layout/bubble_permission_view"
- android:id="@+id/permission_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- />
-
- <View
- android:id="@+id/divider"
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:layout_gravity="bottom"
- android:background="?android:attr/dividerHorizontal"/>
-
- </FrameLayout>
+ android:focusable="true"
+ android:text="@string/manage_bubbles_text"
+ android:textColor="?attr/wallpaperTextColor"/>
</com.android.systemui.bubbles.BubbleExpandedView>
diff --git a/packages/SystemUI/res/layout/bubble_flyout.xml b/packages/SystemUI/res/layout/bubble_flyout.xml
index 0e4d298..5f773f4 100644
--- a/packages/SystemUI/res/layout/bubble_flyout.xml
+++ b/packages/SystemUI/res/layout/bubble_flyout.xml
@@ -13,18 +13,13 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="@dimen/bubble_flyout_pointer_size"
- android:paddingRight="@dimen/bubble_flyout_pointer_size">
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
- android:id="@+id/bubble_flyout"
+ android:id="@+id/bubble_flyout_text_container"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:background="@drawable/bubble_flyout"
+ android:clipToPadding="false"
android:paddingLeft="@dimen/bubble_flyout_padding_x"
android:paddingRight="@dimen/bubble_flyout_padding_x"
android:paddingTop="@dimen/bubble_flyout_padding_y"
@@ -41,4 +36,4 @@
</FrameLayout>
-</FrameLayout>
\ No newline at end of file
+</merge>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/bubble_permission_view.xml b/packages/SystemUI/res/layout/bubble_permission_view.xml
deleted file mode 100644
index df5264c..0000000
--- a/packages/SystemUI/res/layout/bubble_permission_view.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright 2019, The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="@dimen/bubble_permission_height"
- android:animateLayoutChanges="true"
- android:orientation="vertical"
- android:paddingStart="@dimen/bubble_expanded_header_horizontal_padding"
- android:paddingEnd="@dimen/bubble_expanded_header_horizontal_padding">
-
- <!-- App info -->
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_marginTop="@dimen/bubble_expanded_header_horizontal_padding" >
-
- <ImageView
- android:id="@+id/pkgicon"
- android:layout_width="@dimen/bubble_permission_icon_size"
- android:layout_height="@dimen/bubble_permission_icon_size"
- android:layout_centerVertical="true"
- android:layout_marginEnd="3dp"
- />
-
- <TextView
- android:id="@+id/pkgname"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:textAppearance="@*android:style/TextAppearance.Material.Body2"
- android:layout_marginStart="3dp"
- android:layout_marginEnd="2dp"
- android:singleLine="true"
- android:gravity="center_vertical"
- android:layout_centerVertical="true"
- />
- </LinearLayout>
-
- <!-- Actual permission -->
- <TextView
- android:id="@+id/prompt"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/bubbles_prompt"
- style="@*android:style/TextAppearance.DeviceDefault.Notification.Title"/>
-
- <!-- Buttons -->
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="end"
- android:orientation="horizontal">
-
- <TextView
- android:id="@+id/no_bubbles_button"
- android:text="@string/no_bubbles"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:background="@drawable/ripple_drawable"
- style="@style/TextAppearance.NotificationInfo.Button"/>
- <TextView
- android:id="@+id/yes_bubbles_button"
- android:text="@string/yes_bubbles"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:background="@drawable/ripple_drawable"
- style="@style/TextAppearance.NotificationInfo.Button"/>
- </LinearLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/media_projection_dialog_title.xml b/packages/SystemUI/res/layout/media_projection_dialog_title.xml
index c4d784b..b9e39da 100644
--- a/packages/SystemUI/res/layout/media_projection_dialog_title.xml
+++ b/packages/SystemUI/res/layout/media_projection_dialog_title.xml
@@ -15,25 +15,26 @@
limitations under the License.
-->
-<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"
+<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
- android:theme="@style/Theme.MediaProjectionAlertDialog"
+ android:theme="@style/Theme.SystemUI.MediaProjectionAlertDialog"
android:paddingStart="?android:attr/dialogPreferredPadding"
android:paddingEnd="?android:attr/dialogPreferredPadding"
- android:paddingTop="?android:attr/dialogPreferredPadding">
+ android:orientation="vertical">
<ImageView
android:id="@+id/dialog_icon"
android:src="@drawable/ic_media_projection_permission"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:layout_marginBottom="20dp"
- android:layout_centerInParent="true"/>
+ android:layout_height="24dp"
+ android:layout_width="24dp"
+ android:layout_marginTop="18dp"
+ android:layout_marginBottom="12dp"
+ android:layout_gravity="center_horizontal" />
<TextView
android:id="@+id/dialog_title"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_below="@id/dialog_icon"
- android:textColor="?android:attr/colorPrimary"
+ android:textSize="20sp"
+ android:textColor="?android:attr/textColorPrimary"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Title" />
-</RelativeLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml b/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml
deleted file mode 100644
index 133b215..0000000
--- a/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.systemui.tuner.PreviewNavInflater
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:background="@android:color/black"
- android:layout_width="match_parent"
- android:layout_height="@dimen/navigation_bar_size">
-
- <include android:id="@+id/horizontal" layout="@layout/navigation_layout" />
-
- <include android:id="@+id/vertical" layout="@layout/navigation_layout_vertical" />
-
-</com.android.systemui.tuner.PreviewNavInflater>
diff --git a/packages/SystemUI/res/layout/notif_half_shelf.xml b/packages/SystemUI/res/layout/notif_half_shelf.xml
new file mode 100644
index 0000000..a563bb5
--- /dev/null
+++ b/packages/SystemUI/res/layout/notif_half_shelf.xml
@@ -0,0 +1,126 @@
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/half_shelf_dialog"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|bottom"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+>
+
+ <LinearLayout
+ android:id="@+id/half_shelf"
+ android:layout_width="@dimen/qs_panel_width"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="bottom"
+ android:layout_gravity="center_horizontal|bottom"
+ android:background="@drawable/rounded_bg_full" >
+
+ <com.android.systemui.statusbar.notification.row.ChannelEditorListView
+ android:id="@+id/half_shelf_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="bottom"
+ android:orientation="vertical" >
+
+ <com.android.systemui.statusbar.notification.row.AppControlView
+ android:id="@+id/app_control"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:orientation="horizontal" >
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_height="48dp"
+ android:layout_width="48dp"
+ android:padding="8dp" />
+
+ <TextView
+ android:id="@+id/app_name"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_gravity="center"
+ android:padding="8dp"
+ android:gravity="center_vertical|start"
+ android:textSize="15sp"
+ android:ellipsize="end"
+ android:maxLines="1"
+ style="@style/TextAppearance.NotificationInfo.Title" />
+
+ <Switch
+ android:id="@+id/toggle"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:padding="8dp" />
+ </com.android.systemui.statusbar.notification.row.AppControlView>
+ <!-- divider view -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@color/notification_channel_dialog_separator"
+ />
+
+ <!-- ChannelRows get added dynamically -->
+
+ </com.android.systemui.statusbar.notification.row.ChannelEditorListView>
+ <!-- divider view -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@color/notification_channel_dialog_separator"
+ />
+ <RelativeLayout
+ android:id="@+id/bottom_actions"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/notification_guts_button_spacing"
+ android:paddingStart="20dp"
+ android:paddingEnd="20dp" >
+ <TextView
+ android:id="@+id/see_more_button"
+ android:text="@string/see_more_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"
+ android:gravity="start|center_vertical"
+ android:minWidth="@dimen/notification_importance_toggle_size"
+ android:minHeight="@dimen/notification_importance_toggle_size"
+ android:maxWidth="200dp"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ <TextView
+ android:id="@+id/done_button"
+ android:text="@string/inline_ok_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:gravity="end|center_vertical"
+ android:maxWidth="125dp"
+ android:minWidth="@dimen/notification_importance_toggle_size"
+ android:minHeight="@dimen/notification_importance_toggle_size"
+ android:layout_alignParentEnd="true"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ </RelativeLayout>
+ </LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/notif_half_shelf_row.xml b/packages/SystemUI/res/layout/notif_half_shelf_row.xml
new file mode 100644
index 0000000..17ea931
--- /dev/null
+++ b/packages/SystemUI/res/layout/notif_half_shelf_row.xml
@@ -0,0 +1,78 @@
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+
+<com.android.systemui.statusbar.notification.row.ChannelRow
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/half_shelf_row"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:orientation="horizontal" >
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_height="48dp"
+ android:layout_width="48dp"
+ android:layout_gravity="center_vertical"
+ android:padding="8dp"
+ />
+
+ <RelativeLayout
+ android:id="@+id/description_container"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_gravity="center_vertical"
+ android:gravity="left|center_vertical"
+ android:orientation="vertical"
+ >
+ <TextView
+ android:id="@+id/channel_name"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingBottom="0dp"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:gravity="center_vertical|start"
+ android:textSize="14sp"
+ android:ellipsize="end"
+ android:maxLines="1"
+ style="@style/TextAppearance.NotificationInfo.Title"
+ />
+
+ <TextView
+ android:id="@+id/channel_description"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:gravity="center_vertical|start"
+ android:textSize="14sp"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:layout_below="@id/channel_name"
+ style="@style/TextAppearance.NotificationInfo.Secondary"
+ />
+ </RelativeLayout>
+
+ <Switch
+ android:id="@+id/toggle"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:padding="8dp"
+ />
+</com.android.systemui.statusbar.notification.row.ChannelRow>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
new file mode 100644
index 0000000..2b21006
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
@@ -0,0 +1,66 @@
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+ -->
+
+<!-- Extends FrameLayout -->
+<com.android.systemui.statusbar.notification.stack.SectionHeaderView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/notification_section_header_height"
+ android:focusable="true"
+ android:clickable="true"
+ >
+ <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
+ android:id="@+id/backgroundNormal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
+ android:id="@+id/backgroundDimmed"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <LinearLayout
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ >
+ <TextView
+ android:id="@+id/header_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="@dimen/notification_section_header_padding_left"
+ android:text="@string/notification_section_header_gentle"
+ android:textSize="12sp"
+ android:textColor="@color/notification_section_header_label_color"
+ />
+ <ImageView
+ android:id="@+id/btn_clear_all"
+ android:layout_width="@dimen/notification_section_header_height"
+ android:layout_height="@dimen/notification_section_header_height"
+ android:layout_marginRight="4dp"
+ android:src="@drawable/status_bar_notification_section_header_clear_btn"
+ android:contentDescription="@string/accessibility_notification_section_header_gentle_clear_all"
+ />
+ </LinearLayout>
+
+ <com.android.systemui.statusbar.notification.FakeShadowView
+ android:id="@+id/fake_shadow"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</com.android.systemui.statusbar.notification.stack.SectionHeaderView>
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 4cf5f85..a914930 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -69,7 +69,7 @@
android:layout_height="match_parent"
android:importantForAccessibility="no"
sysui:ignoreRightInset="true"
- />
+ />
<LinearLayout
android:id="@+id/lock_icon_container"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index e018706..aa545fa 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Donker-tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is gedeaktiveer"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is geaktiveer"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Moenie weer wys nie"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Vee alles uit"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Bestuur"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Ligte kennigewings"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Vee alle ligte kennisgewings uit"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Kennisgewings onderbreek deur Moenie Steur Nie"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Begin nou"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Geen kennisgewings nie"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Skerm is vasgespeld"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Terug en Oorsig om dit te ontspeld."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Terug en Tuis om dit te ontspeld."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Dit hou dit in sig totdat jy dit ontspeld. Swiep op en hou om te ontspeld."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Oorsig om dit te ontspeld."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Tuis om dit te ontspeld."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Raak en hou die Terug- en Oorsig-knoppie om hierdie skerm te ontspeld"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Hou aan om kennisgewings van hierdie program af te wys?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Lig"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Geprioritiseerd"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Altyd stil. Wys op aftrekskerm."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Altyd stil. Wys op aftrekskerm en statusbalk."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Altyd stil. Wys op aftrekskerm en op sluitskerm."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Altyd stil. Wys op aftrekskerm, statusbalk en op sluitskerm."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Maak geluid en wys op aftrekskerm, statusbalk en op sluitskerm."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Help jou om te fokus met kennisgewings wat net op die aftrekskerm is. Altyd stil."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Wys prioriteitkennisgewings hieronder. Altyd stil."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Wys prioriteitkennisgewings hieronder. Altyd stil."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Wys prioriteitkennisgewings hieronder. Altyd stil."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Trek jou aandag met klank en \'n statusbalk-ikoon. Wys op sluitskerm."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Hierdie kennisgewings kan nie gewysig word nie."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Hierdie groep kennisgewings kan nie hier opgestel word nie"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Instaanbediener-kennisgewing"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Hierdie program gebruik tans die kamera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Hierdie program gebruik tans die mikrofoon."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Maak <xliff:g id="APP_NAME">%1$s</xliff:g> oop"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Instellings vir <xliff:g id="APP_NAME">%1$s</xliff:g>-borrels"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Laat borrels vanaf <xliff:g id="APP_NAME">%1$s</xliff:g> toe?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Bestuur"</string>
<string name="no_bubbles" msgid="337101288173078247">"Weier"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Laat toe"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Vra my later"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Beweeg na regs bo"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Beweeg na links onder"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Beweeg na regs onder"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 8a390cb..dfe34c7 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -271,8 +271,7 @@
<string name="gps_notification_searching_text" msgid="8574247005642736060">"ለGPS በመፈለግ ላይ"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"በ GPS የተዘጋጀ ሥፍራ"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"የአካባቢ ጥያቄዎች ነቅተዋል"</string>
- <!-- no translation found for accessibility_sensors_off_active (157126524598525432) -->
- <skip />
+ <string name="accessibility_sensors_off_active" msgid="157126524598525432">"ዳሳሾች ጠፍተዋል ገቢር"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
<string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
@@ -370,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> ላይ ይበራል"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"እስከ <xliff:g id="TIME">%s</xliff:g> ድረስ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"ጨለማ ገጽታ"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"ኤንኤፍሲ"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"ኤንኤፍሲ ተሰናክሏል"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"ኤንኤፍሲ ነቅቷል"</string>
@@ -449,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"ዳግመኛ አታሳይ"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"ሁሉንም አጽዳ"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"ያቀናብሩ"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"ገር ማሳወቂያዎች"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"ረጋ ያሉትን ማሳወቂያዎች በሙሉ ያጽዱ"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"ማሳወቂያዎች በአትረብሽ ባሉበት ቆመዋል"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"አሁን ጀምር"</string>
<string name="empty_shade_text" msgid="708135716272867002">"ምንም ማሳወቂያ የለም"</string>
@@ -528,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"ማያ ገጽ ተሰክቷል"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል ተመለስ እና አጠቃላይ ዕይታ የሚለውን ይጫኑ እና ይያዙ።"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል ተመለስ እና መነሻ የሚለውን ይንኩ እና ይያዙ።"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"እስኪነቅሉት ድረስ ይህ በእይታ ውስጥ ያቆየዋል። ለመንቀል ወደ ላይ ጠረግ አድርገው ይያዙ።"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል አጠቃላይ ዕይታ ተጭነው ይያዙ።"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል መነሻ የሚለውን ይንኩ እና ይያዙ።"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"ይህን ማያ ገጽ ለመንቀል ተመለስ እና አጠቃላይ ዕይታ አዝራሮችን ይንኩ እና ይያዙ"</string>
@@ -639,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"ከዚህ መተግበሪያ ማሳወቂያዎችን ማሳየት ይቀጥል?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"ረጋ ያለ"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"ቅድሚያ የተሰጠው"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"ሁልጊዜ ጸጥታ። በወደ ታች ተጎታች ጥላ ውስጥ ያሳያል።"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"ሁልጊዜ ጸጥታ። በወደ ታች ተጎታች ዝርዝር ጥላ እና በሁነታ አሞሌው ውስጥ ያሳያል"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"ሁልጊዜ ጸጥታ። በወደ ታች ተጎታች ዝርዝር ጥላ ውስጥ እና በማያ ገጽ መቆለፊያ ገጽ ላይ ያሳያል።"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"ሁልጊዜ ጸጥታ። በወደ ታች ተጎታች ጥላ፣ በሁነታ አሞሌ እና በመቆለፊያ ማያ ገጽ ውስጥ ያሳያል።"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"በወደ ታች ተጎታች ዝርዝር ጥላ እና በማያ ገጽ መቆለፊያ ውስጥ ድምፅን እና ማሳያዎችን ፍጠር።"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"በወደታች ተጎችታች ጥላ ውስጥ ብቻ በማሳወቂያዎች ላይ እንዲያተኩሩ ያግዝዎታል። ሁልጊዜ ጸጥታ።"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"ከዚህ በታች ቅድሚያ ተሰጪ ማሳወቂያዎችን ያሳያል። ሁልጊዜ ጸጥታ።"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"ከዚህ በታች ቅድሚያ ተሰጪ ማሳወቂያዎችን ያሳያል። ሁልጊዜ ጸጥታ።"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"ከዚህ በታች ቅድሚያ ተሰጪ ማሳወቂያዎችን ያሳያል። ሁልጊዜ ጸጥታ።"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ከድምፅ እና የሁኔታ አሞሌ አዶ ጋር የእርስዎን ትኩረት ይስባል። በማያ ገጽ ቁልፍ ላይ ያሳያል።"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"እነዚህ ማሳወቂያዎች ሊሻሻሉ አይችሉም።"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"የማሳወቂያዎች ይህ ቡድን እዚህ ላይ ሊዋቀር አይችልም"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"ተኪ ማሳወቂያ"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"ይህ መተግበሪያ ካሜራውን እየተጠቀመ ነው።"</string>
<string name="appops_microphone" msgid="741508267659494555">"ይህ መተግበሪያ ማይክሮፎኑን እየተጠቀመ ነው።"</string>
@@ -912,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> ክፈት"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"ቅንብሮች ለ <xliff:g id="APP_NAME">%1$s</xliff:g> አረፋዎች"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"ከ <xliff:g id="APP_NAME">%1$s</xliff:g> አረፋዎች ይፈቀዱ?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"ያቀናብሩ"</string>
<string name="no_bubbles" msgid="337101288173078247">"ከልክል"</string>
<string name="yes_bubbles" msgid="668809525728633841">"ፍቀድ"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"በኋላ ጠይቀኝ"</string>
@@ -922,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"ወደ ላይኛው ቀኝ አንቀሳቅስ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"የግርጌውን ግራ አንቀሳቅስ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"ታችኛውን ቀኝ ያንቀሳቅሱ"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 84c9332..8784217 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -377,6 +377,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"تفعيل الإعداد في <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"حتى <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"مظهر الألوان الداكنة"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"الاتصالات قصيرة المدى (NFC)"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"تم إيقاف الاتصال القريب المدى"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"تم تفعيل الاتصال القريب المدى"</string>
@@ -460,6 +462,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"عدم الإظهار مرة أخرى"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"محو الكل"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"إدارة"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"إشعارات بسيطة"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"محو جميع الإشعارات البسيطة"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"تم إيقاف الإشعارات مؤقتًا وفقًا لإعداد \"الرجاء عدم الإزعاج\""</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"البدء الآن"</string>
<string name="empty_shade_text" msgid="708135716272867002">"ليس هناك أي اشعارات"</string>
@@ -539,6 +543,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"تم تثبيت الشاشة"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار الزرين \"رجوع\" و\"نظرة عامة\" لإزالة التثبيت."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار الزرين \"رجوع\" و\"الشاشة الرئيسية\" لإزالة التثبيت."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. مرّر الشاشة بسرعة للأعلى مع الاستمرار لإزالة تثبيت الشاشة."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار زر \"نظرة عامة\" لإزالة التثبيت."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار زر \"الشاشة الرئيسية\" لإزالة التثبيت."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"لإزالة تثبيت هذه الشاشة، يمكنك أن تلمس مع الاستمرار زرّي \"رجوع\" و\"نظرة عامة\"."</string>
@@ -650,14 +655,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"هل تريد الاستمرار في تلقي إشعارات من هذا التطبيق؟"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"الإشعارات الهادئة"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"له الأولوية"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"كتم الصوت دائمًا: يظهر هذا الإعداد في خيار منسدل."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"كتم الصوت دائمًا: سيظهر هذا الإعداد في خيار منسدل وفي شريط الحالة."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"كتم الصوت دائمًا: يظهر هذا الاختيار في خيار منسدِل وعلى شاشة التأمين."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"كتم الصوت دائمًا: يظهر هذا الإعداد في خيار منسدل وفي شريط الحالة وفي شاشة التأمين."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"ستسمع صوتًا وسيظهر لك هذا الإعداد في خيار منسدل وفي شريط الحالة وفي شاشة التأمين."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"لمساعدتك على التركيز، يتم عرض هذه الإشعارات ضمن \"مركز الإشعارات\" فقط. كتم الصوت دائمًا."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"يتم عرض هذه الإشعارات أسفل الإشعارات ذات الأولوية. كتم الصوت دائمًا."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"يتم عرض هذه الإشعارات أسفل الإشعارات ذات الأولوية. كتم الصوت دائمًا."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"يتم عرض هذه الإشعارات أسفل الإشعارات ذات الأولوية. كتم الصوت دائمًا."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"تلفت هذه الإشعارات انتباهك وذلك باستخدام الصوت ورمز \"شريط الحالة\". يتم عرض هذه الإشعارات على \"شاشة التأمين\"."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"يتعذّر تعديل هذه الإشعارات."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"يتعذّر ضبط مجموعة الإشعارات هذه هنا."</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"إشعار مستند إلى خادم وكيل"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"يستخدم هذا التطبيق الكاميرا."</string>
<string name="appops_microphone" msgid="741508267659494555">"يستخدم هذا التطبيق الميكروفون."</string>
@@ -931,6 +939,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"فتح <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"إعداد الفقاعات التفسيرية على <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"هل تريد السماح بالفقاعات التفسيرية من <xliff:g id="APP_NAME">%1$s</xliff:g>؟"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"إدارة"</string>
<string name="no_bubbles" msgid="337101288173078247">"رفض"</string>
<string name="yes_bubbles" msgid="668809525728633841">"سماح"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"اسألني لاحقًا"</string>
@@ -941,4 +950,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"الانتقال إلى أعلى اليسار"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"نقل إلى أسفل يمين الشاشة"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"نقل إلى أسفل اليسار"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index b42a2c6..c2fbda5 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>ত অন কৰক"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> পৰ্যন্ত"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"গাঢ় ৰঙৰ থীম"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC নিষ্ক্ৰিয় হৈ আছে"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC সক্ষম হৈ আছে"</string>
@@ -448,6 +450,10 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"পুনৰাই নেদেখুৱাব"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"সকলো মচক"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"পৰিচালনা"</string>
+ <!-- no translation found for notification_section_header_gentle (8356064473678167305) -->
+ <skip />
+ <!-- no translation found for accessibility_notification_section_header_gentle_clear_all (4270384919249494640) -->
+ <skip />
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"অসুবিধা নিদিব-ই জাননী পজ কৰিছে"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"এতিয়াই আৰম্ভ কৰক"</string>
<string name="empty_shade_text" msgid="708135716272867002">"কোনো জাননী নাই"</string>
@@ -527,6 +533,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"স্ক্ৰীণ পিন কৰা হ’ল"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"এই কাৰ্যই আপুনি আনপিন নকৰালৈকে ইয়াক দেখা পোৱা অৱস্থাত ৰাখে। আনপিন কৰিবলৈ \'পিছলৈ যাওক\' আৰু \'অৱলোকন\'-ত স্পৰ্শ কৰি থাকক।"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"এই কাৰ্যই আপুনি আনপিন নকৰালৈকে ইয়াক দেখা পোৱা অৱস্থাত ৰাখে। আনপিন কৰিবলৈ পিছলৈ যাওক আৰু হ\'মত স্পৰ্শ কৰি সেঁচি ধৰক।"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"এই কাৰ্যই আপুনি আনপিন নকৰালৈকে ইয়াক দেখা পোৱা অৱস্থাত ৰাখে। আনপিন কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক।"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"এই কাৰ্যই আপুনি আনপিন নকৰালৈকে ইয়াক দেখা পোৱা অৱস্থাত ৰাখে। আনপিন কৰিবলৈ \'অৱলোকন\'-ত স্পৰ্শ কৰি থাকক।"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"এই কাৰ্যই আপুনি আনপিন নকৰালৈকে ইয়াক দেখা পোৱা অৱস্থাত ৰাখে। আনপিন কৰিবলৈ পিছলৈ যাওক আৰু হ\'মত স্পৰ্শ কৰি সেঁচি ধৰক।"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"এই স্ক্ৰীণখন আনপিন কৰিবলৈ পিছলৈ যাওক আৰু অৱলোকন বুটামত স্পৰ্শ কৰি হেঁচি ধৰক।"</string>
@@ -638,14 +645,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"এই এপটোৰ জাননী দেখুওৱাই থাকিব লাগিবনে?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"সাধাৰণ"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"অগ্ৰাধিকাৰপ্ৰাপ্ত"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"সদায় নিৰৱ। পুল ডাউন শ্বেডত প্ৰদর্শন কৰে।"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"সদায় নিৰৱ। পুল ডাউন শ্বেড & স্থিতিৰ দণ্ডত প্ৰদর্শন কৰে।"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"সদায় নিৰৱ। পুল ডাউন শ্বেড & লক স্ক্ৰীণত প্ৰদর্শন কৰে।"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"সদায় নিৰৱ। পুল ডাউন শ্বেড, স্থিতি দণ্ড & লক স্ক্ৰীণত প্ৰদর্শন কৰে।"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"শব্দ কৰে আৰু পুল ডাউন শ্বেড, স্থিতি দণ্ড & লক স্ক্ৰীণত প্ৰদর্শন কৰে।"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"আপুনি যাতে অসুবিধা নাপায়, তাৰ বাবে কেৱল পুল-ডাউন শ্বেডত এই জাননী দেখুৱায়। সদায় নিৰৱ।"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"অগ্ৰাধিকাৰপ্ৰাপ্ত জাননীসমূহৰ তলত দেখুৱায়। সদায় নিৰৱ।"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"অগ্ৰাধিকাৰপ্ৰাপ্ত জাননীসমূহৰ তলত দেখুৱায়। সদায় নিৰৱ।"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"অগ্ৰাধিকাৰপ্ৰাপ্ত জাননীসমূহৰ তলত দেখুৱায়। সদায় নিৰৱ।"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ধ্বনি আৰু স্থিতি দণ্ডৰ আইকনৰ জৰিয়তে আপোনাৰ মনোযোগ আকৰ্ষণ কৰে। লক স্ক্ৰীণত দেখুৱায়।"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"এই জাননীসমূহ সংশোধন কৰিব নোৱাৰি।"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"এই ধৰণৰ জাননীবোৰ ইয়াত কনফিগাৰ কৰিব পৰা নাযায়"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"প্ৰক্সি হিচাপে পঠিওৱা জাননী"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"এই এপে কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string>
<string name="appops_microphone" msgid="741508267659494555">"এই এপে মাইক্ৰ\'ফ\'ন ব্য়ৱহাৰ কৰি আছে।"</string>
@@ -911,6 +921,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> খোলক"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবলৰ ছেটিংসমূহ"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবলসমূহক অনুমতি দিয়ক?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"পৰিচালনা কৰক"</string>
<string name="no_bubbles" msgid="337101288173078247">"অস্বীকাৰ কৰক"</string>
<string name="yes_bubbles" msgid="668809525728633841">"অনুমতি দিয়ক"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"মোক পিছত সুধিব"</string>
@@ -921,4 +932,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"শীৰ্ষৰ সোঁফালে নিয়ক"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"বুটামটো বাওঁফালে নিয়ক"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"তলৰ সোঁফালে নিয়ক"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index a7aaca9..5fab3d6 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> olduqda aktiv ediləcək"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> vaxtına qədər"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tünd Tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC deaktiv edilib"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC aktiv edilib"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Daha göstərmə"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Hamısını silin"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"İdarə edin"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Daha az əhəmiyyətli bildirişlər"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Az əhəmiyyətli bildirişlərin hamısını silin"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Bildirişlər \"Narahat Etməyin\" rejimi tərəfindən dayandırıldı"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"İndi başlayın"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Heç bir bildiriş yoxdur"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekrana sancaq taxıldı"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri və İcmal düymələrinə basıb saxlayın."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri və Əsas səhifə düymələrinə basıb saxlayın."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Bu, onu çıxarana qədər görünəcək. Çıxarmaq üçün yuxarı sürüşdürün & basıb saxlayın."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri düyməsinə basıb saxlayın."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Əsas səhifə düyməsinə basıb saxlayın."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Bu ekrandan sancağı götürmək üçün Geri və İcmal düymələrinə basıb saxlayın"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Bu tətbiqin bildirişləri göstərilməyə davam edilsin?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Daha az əhəmiyyətli"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Mühüm"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Həmişə səssiz. Aşağı açılan ekranda görünür."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Həmişə səssiz. Aşağı açılan ekran və status panelidə görünür."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Həmişə səssiz. Aşağı açılan ekran və kilid ekranında görünür."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Həmişə səssiz. Aşağı açılan ekran, status paneli və kilid ekranında görünür."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Səsli rejimdə aşağı açılan ekran, status paneli və kilid ekranında görünür."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Yalnız aşağı açılan siyahıda bildirişlərə fokuslanmağınıza kömək edir. Həmişə səssiz."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Mühüm bildirişlərin aşağısında göstərilir. Həmişə səssiz."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Mühüm bildirişlərin aşağısında göstərilir. Həmişə səssiz."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Mühüm bildirişlərin aşağısında göstərilir. Həmişə səssiz."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Səs & status paneli ikonası ilə diqqətinizi cəlb edir. Ekran kilidini göstərir."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Bu bildirişlər dəyişdirilə bilməz."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Bu bildiriş qrupunu burada konfiqurasiya etmək olmaz"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Proksi bildirişi"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Bu tətbiq kameradan istifadə edir."</string>
<string name="appops_microphone" msgid="741508267659494555">"Bu tətbiq mikrofondan istifadə edir."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqini açın"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> qabarcıqları üçün ayarlar"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> qabarcıqlarına icazə verilsin?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"İdarə edin"</string>
<string name="no_bubbles" msgid="337101288173078247">"İmtina edin"</string>
<string name="yes_bubbles" msgid="668809525728633841">"İcazə verin"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Sonra soruşun"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Yuxarıya sağa köçürün"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Aşağıya sola köçürün"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Aşağıya sağa köçürün"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 2b06e89..421fc76 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -208,10 +208,10 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obaveštenje je odbačeno."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Prozor sa obaveštenjima."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Brza podešavanja."</string>
- <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"Zaključani ekran."</string>
+ <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"Zaključan ekran."</string>
<string name="accessibility_desc_settings" msgid="3417884241751434521">"Podešavanja"</string>
<string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"Pregled."</string>
- <string name="accessibility_desc_work_lock" msgid="4288774420752813383">"Zaključani ekran za posao"</string>
+ <string name="accessibility_desc_work_lock" msgid="4288774420752813383">"Zaključan ekran za posao"</string>
<string name="accessibility_desc_close" msgid="7479755364962766729">"Zatvori"</string>
<string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wi-Fi je isključen."</string>
@@ -371,6 +371,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tamna tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je onemogućen"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je omogućen"</string>
@@ -451,6 +453,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ne prikazuj ponovo"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Obriši sve"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Upravljajte"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Diskretna obaveštenja"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Obrišite sva diskretna obaveštenja"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Obaveštenja su pauzirana režimom Ne uznemiravaj"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Započni odmah"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Nema obaveštenja"</string>
@@ -530,6 +534,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekran je zakačen"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Na ovaj način se ovo stalno prikazuje dok ga ne otkačite. Dodirnite i zadržite Nazad i Pregled da biste ga otkačili."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Na ovaj način se ovo stalno prikazuje dok ga ne otkačite. Dodirnite i zadržite Nazad i Početna da biste ga otkačili."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Na ovaj način se stalno prikazuje dok ga ne otkačite. Prevucite nagore i zadržite da biste ga otkačili."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Na ovaj način se ovo stalno prikazuje dok ga ne otkačite. Dodirnite i zadržite Pregled da biste ga otkačili."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Na ovaj način se ovo stalno prikazuje dok ga ne otkačite. Dodirnite i zadržite Početna da biste ga otkačili."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Da biste otkačili ovaj ekran, dodirnite i zadržite dugmad Nazad i Pregled"</string>
@@ -641,14 +646,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Želite li da se obaveštenja iz ove aplikacije i dalje prikazuju?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Diskretno"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritetno"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Uvek nečujno. Prikazuje se na padajućoj traci."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Uvek nečujno. Prikazuje se na padajućoj traci i statusnoj traci."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Uvek nečujno. Prikazuje se na padajućoj traci i zaključanom ekranu."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Uvek nečujno. Prikazuje se na padajućoj traci, statusnoj traci i zaključanom ekranu."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Prikazuje se na padajućoj traci, statusnoj traci i zaključanom ekranu uz zvučno obaveštenje."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Pomaže vam da se fokusirate. Obaveštenja su samo na padajućoj traci. Uvek nečujno."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Prikazuje se ispod prioritetnih obaveštenja. Uvek nečujno."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Prikazuje se ispod prioritetnih obaveštenja. Uvek nečujno."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Prikazuje se ispod prioritetnih obaveštenja. Uvek nečujno."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Privlači vam pažnju pomoću zvuka i ikone statusne trake. Prikazuje se na zaključanom ekranu."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Ova obaveštenja ne mogu da se menjaju."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Ova grupa obaveštenja ne može da se konfiguriše ovde"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Obaveštenje preko proksija"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Ova aplikacija koristi kameru."</string>
<string name="appops_microphone" msgid="741508267659494555">"Ova aplikacija koristi mikrofon."</string>
@@ -822,7 +830,7 @@
<string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otvori podešavanja za <xliff:g id="ID_1">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Izmeni redosled podešavanja."</string>
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. strana od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
- <string name="tuner_lock_screen" msgid="5755818559638850294">"Zaključani ekran"</string>
+ <string name="tuner_lock_screen" msgid="5755818559638850294">"Zaključan ekran"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string>
@@ -916,6 +924,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Otvorite <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Podešavanja za <xliff:g id="APP_NAME">%1$s</xliff:g> oblačiće"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Želite li da omogućite oblačiće iz aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Upravljajte"</string>
<string name="no_bubbles" msgid="337101288173078247">"Odbij"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Dozvoli"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Pitaj me kasnije"</string>
@@ -926,4 +935,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Premesti gore desno"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Premesti dole levo"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Premesti dole desno"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 6d8b543..0da78b6 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -375,6 +375,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Уключыць у <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Да <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Цёмная тэма"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC адключаны"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC уключаны"</string>
@@ -456,6 +458,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Не паказваць зноў"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Ачысціць усё"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Кіраваць"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Апавяшчэнні ў ціхім рэжыме"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Выдаліць усе апавяшчэнні ў ціхім рэжыме"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Паказ апавяшчэнняў прыпынены ў рэжыме \"Не турбаваць\""</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Пачаць зараз"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Апавяшчэнняў няма"</string>
@@ -535,6 +539,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Экран замацаваны"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Будзе паказвацца, пакуль не адмацуеце. Каб адмацаваць, краніце і ўтрымлівайце кнопкі \"Назад\" і \"Агляд\"."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Будзе паказвацца, пакуль не адмацуеце. Каб адмацаваць, націсніце і ўтрымлівайце кнопкі \"Назад\" і \"Галоўны экран\"."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Будзе паказвацца, пакуль не адмацуеце Каб адмацаваць, прагартайце ўверх, утрымліваючы палец на экране"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Будзе паказвацца, пакуль не адмацуеце. Каб адмацаваць, краніце і ўтрымлівайце кнопку \"Агляд\"."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Будзе паказвацца, пакуль не адмацуеце. Каб адмацаваць, націсніце і ўтрымлівайце кнопку \"Галоўны экран\"."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Каб адмацаваць гэты экран, націсніце і ўтрымлівайце кнопкі \"Назад\" і \"Агляд\""</string>
@@ -646,14 +651,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Працягваць паказваць апавяшчэнні гэтай праграмы?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Ціхі рэжым"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Прыярытэтныя"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Заўсёды без гуку. Паказваецца на апушчанай шторцы."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Заўсёды без гуку. Паказваецца на апушчанай шторцы і на панэлі стану."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Заўсёды без гуку. Паказваецца на апушчанай шторцы і на экране блакіроўкі."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Заўсёды без гуку. Паказваецца на апушчанай шторцы, панэлі стану і на экране блакіроўкі."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Паказваецца з гукам на апушчанай шторцы, панэлі стану і на экране блакіроўкі."</string>
- <string name="notification_unblockable_desc" msgid="4556908766584964102">"Гэтыя апавяшчэнні можна змяніць."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Дапамагае не адцягваць увагу, паказваючы апавяшчэнні толькі на апушчанай шторцы. Заўсёды без гуку."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Паказвае ўнізе апавяшчэнні з высокім прыярытэтам. Заўсёды без гуку."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Паказвае ўнізе апавяшчэнні з высокім прыярытэтам. Заўсёды без гуку."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Паказвае ўнізе апавяшчэнні з высокім прыярытэтам. Заўсёды без гуку."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Прываблівае ўвагу гукам і значком на панэлі стану. Паказвае на экране блакіроўкі."</string>
+ <string name="notification_unblockable_desc" msgid="4556908766584964102">"Гэтыя апавяшчэнні нельга змяніць."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Тут канфігурыраваць гэту групу апавяшчэнняў забаронена"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Праксіраванае апавяшчэнне"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Гэта праграма выкарыстоўвае камеру."</string>
<string name="appops_microphone" msgid="741508267659494555">"Гэта праграма выкарыстоўвае мікрафон."</string>
@@ -923,6 +931,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Адкрыць праграму \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Налады дыялогаў у праграме \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Дазволіць дыялогі з праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Кіраваць"</string>
<string name="no_bubbles" msgid="337101288173078247">"Адмовіць"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Дазволіць"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Спытаць пазней"</string>
@@ -933,4 +942,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Перамясціце правей і вышэй"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Перамясціць лявей і ніжэй"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Перамясціць правей і ніжэй"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 3c3a2e4..40148d4 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ще се включи в <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Тъмна тема"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"КБП"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"КБП е деактивирана"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"КБП е активирана"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Да не се показва отново"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Изчистване на всички"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Управление"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Ненатрапчиви известия"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Изчистване на всички ненатрапчиви известия"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Известията са поставени на пауза от режима „Не безпокойте“"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Стартиране сега"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Няма известия"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Екранът е фиксиран"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Екранът ще се показва, докато не го освободите с докосване и задържане на бутона за връщане назад и този за общ преглед."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Екранът ще се показва, докато не го освободите с докосване и задържане на бутона за връщане назад и „Начало“."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Екранът ще остане на преден план, докато не го освободите. Прекарайте пръст нагоре и задръжте за освобождаване."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Екранът ще се показва, докато не го освободите с докосване и задържане на бутона за общ преглед."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Екранът ще се показва, докато не го освободите с докосване и задържане на бутона „Начало“."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"За да освободите този екран, докоснете и задръжте бутона за връщане назад и този за общ преглед"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Да продължат ли да се показват известията от това приложение?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Ненатрапчиви известия"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Приоритетни известия"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Винаги в тих режим. Показва се в падащия панел."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Винаги в тих режим. Показва се в падащия панел и лентата на състоянието."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Винаги в тих режим. Показва се в падащия панел и на заключения екран."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Винаги в тих режим. Показва се в падащия панел, лентата на състоянието и на заключения екран."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Издава звук и се показва в падащия панел, лентата на състоянието и на заключения екран."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Помага ви да се съсредоточите, като известията се показват само в падащия панел. Винаги в тих режим."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Показва се под приоритетните известия. Винаги в тих режим."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Показва се под приоритетните известия. Винаги в тих режим."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Показва се под приоритетните известия. Винаги в тих режим."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Привлича вниманието ви със звук и икона в лентата на състоянието. Показва се на заключения екран."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Тези известия не могат да бъдат променяни."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Тази група от известия не може да бъде конфигурирана тук"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Известие, получено чрез делегиране"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Това приложение използва камерата."</string>
<string name="appops_microphone" msgid="741508267659494555">"Това приложение използва микрофона."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Отваряне на „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Настройки за балончетата за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Да се разрешат ли балончетата от <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Управление"</string>
<string name="no_bubbles" msgid="337101288173078247">"Отказ"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Разрешаване"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Попитайте ме по-късно"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Преместване горе вдясно"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Преместване долу вляво"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Преместване долу вдясно"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 2cd48a3..56bb9e7 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> এ চালু হবে"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> পর্যন্ত"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"গাঢ় থিম"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC অক্ষম করা আছে"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC সক্ষম করা আছে"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"আর দেখাবেন না"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"সবকিছু সাফ করুন"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"পরিচালনা করুন"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"সাইলেন্ট মোডের বিজ্ঞপ্তি"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"সাইলেন্ট মোডের বিজ্ঞপ্তি মুছুন"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\'বিরক্ত করবেন না\' দিয়ে বিজ্ঞপ্তি পজ করা হয়েছে"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"এখন শুরু করুন"</string>
<string name="empty_shade_text" msgid="708135716272867002">"কোনো বিজ্ঞপ্তি নেই"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"স্ক্রিন পিন করা হয়েছে"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"এটি আপনি আনপিন না করা পর্যন্ত এটিকে প্রদর্শিত করবে৷ আনপিন করতে ফিরুন এবং ওভারভিউ স্পর্শ করে ধরে থাকুন।"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"এর ফলে আপনি এটি আনপিন না করা পর্যন্ত এটি দেখানো হতে থাকবে। আনপিন করতে \"ফিরে যান\" এবং \"হোম\" বোতামদুটি ট্যাপ করে ধরে রাখুন।"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"এর ফলে আপনি আনপিন না করা পর্যন্ত এটি দেখানো হতে থাকবে। আনপিন করার জন্য উপরের দিকে সোয়াইপ করে ধরে থাকুন"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"এটি আপনি আনপিন না করা পর্যন্ত এটিকে প্রদর্শিত করবে৷ আনপিন করতে ওভারভিউ স্পর্শ করে ধরে থাকুন৷"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"এর ফলে আপনি এটি আনপিন না করা পর্যন্ত এটি দেখানো হতে থাকবে। আনপিন করতে \"হোম\" বোতামটি ট্যাপ করে ধরে রাখুন।"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"এই স্ক্রিনটি আনপিন করতে \"ফিরে যান\" এবং \"এক নজরে\" বোতামদুটি ট্যাপ করে ধরে রাখুন"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"এই অ্যাপের বিজ্ঞপ্তি পরেও দেখে যেতে চান?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"সাইলেন্ট মোডে"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"অগ্রাধিকার দেওয়া হয়েছে"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"সবসময় নীরব। পুল-ডাউন শেডে দেখানো হয়।"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"সবসময় নীরব। পুল-ডাউন শেড ও স্ট্যাটাস বারে দেখানো হয়।"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"সবসময় নীরব। পুল-ডাউন শেড ও লক স্ক্রিনে দেখানো হয়।"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"সবসময় নীরব। পুল-ডাউন শেড, স্ট্যাটাস বার ও লক স্ক্রিনে দেখানো হয়।"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"শব্দ করে এবং পুল-ডাউন শেড, স্ট্যাটাস বার ও লক স্ক্রিনে দেখানো হয়।"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"আপনি যাতে বিরক্ত না হন, তার জন্য শুধুমাত্র পুল-ডাউন শেডে এই বিজ্ঞপ্তি দেখায়। সবসময় সাইলেন্ট।"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"অগ্রাধিকারযুক্ত বিজ্ঞপ্তির নিচে দেখানো হয়। সবসময় সাইলেন্ট।"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"অগ্রাধিকারযুক্ত বিজ্ঞপ্তির নিচে দেখানো হয়। সবসময় সাইলেন্ট।"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"অগ্রাধিকারযুক্ত বিজ্ঞপ্তির নিচে দেখানো হয়। সবসময় সাইলেন্ট।"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"সাউন্ড ও স্ট্যাটাস বার আইকনের সাহায্যে দৃষ্টি আকর্ষণ করে। এটি লক স্ক্রিনে দেখা যায়।"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"এই বিজ্ঞপ্তিগুলি পরিবর্তন করা যাবে না।"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"এই সমস্ত বিজ্ঞপ্তিকে এখানে কনফিগার করা যাবে না"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"প্রক্সি করা বিজ্ঞপ্তি"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"এই অ্যাপটি ক্যামেরা ব্যবহার করছে।"</string>
<string name="appops_microphone" msgid="741508267659494555">"এই অ্যাপটি মাইক্রোফোন ব্যবহার করছে।"</string>
@@ -765,7 +773,7 @@
<string name="right_keycode" msgid="708447961000848163">"ডানদিকের কিকোড"</string>
<string name="left_icon" msgid="3096287125959387541">"বাঁ দিকের আইকন"</string>
<string name="right_icon" msgid="3952104823293824311">"ডানদিকের আইকন"</string>
- <string name="drag_to_add_tiles" msgid="230586591689084925">"টাইল যোগ করতে ট্যাপ করে টেনে আনুন"</string>
+ <string name="drag_to_add_tiles" msgid="230586591689084925">"টাইল যোগ করতে ধরে থেকে টেনে আনুন"</string>
<string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"টাইলগুলি আবার সাজানোর জন্য ধরে থেকে টেনে আনুন"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"সরানোর জন্য এখানে টেনে আনুন"</string>
<string name="drag_to_remove_disabled" msgid="2390968976638993382">"অন্তত ৬টি টাইল রাখতে হবে"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> খুলুন"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> বাবলের জন্য সেটিংস"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপের বাবল চালু করবেন?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"ম্যানেজ করা"</string>
<string name="no_bubbles" msgid="337101288173078247">"খারিজ করুন"</string>
<string name="yes_bubbles" msgid="668809525728633841">"অনুমতি দিন"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"আমাকে পরে জিজ্ঞাসা করুন"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"উপরে ডানদিকে সরান"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"নিচে বাঁদিকে সরান"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"নিচে ডান দিকে সরান"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 8944a47..443e647 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -370,7 +370,9 @@
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Do svitanja"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
- <string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema po mraku"</string>
+ <string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tamna tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je onemogućen"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je omogućen"</string>
@@ -451,6 +453,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ne prikazuj opet"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Očisti sve"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Upravljaj"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Diskretna obavještenja"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Obriši sva diskretna obavještenja"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Obavještenja su pauzirana načinom rada Ne ometaj"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Započni odmah"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Nema obavještenja"</string>
@@ -530,6 +534,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekran je prikačen"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Nazad."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Na ovaj način ekran ostaje prikazan dok ga ne otkačite. Da otkačite ekran, dodirnite i držite dugme Nazad i Početna."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Na ovaj način ekran ostaje prikazan dok ga ne otkačite. Prevucite prema gore i držite da otkačite."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Pregled."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Na ovaj način ekran ostaje prikazan dok ga ne otkačite. Da okačite ekran, dodirnite ili držite dugme Početna."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Dodirnite i držite dugmad Nazad i Pregled da otkačite ekran"</string>
@@ -643,14 +648,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Nastaviti prikazivanje obavještenja iz ove aplikacije?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Diskretno"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritetno"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Uvijek nečujno. Prikazuje se na padajućoj traci."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Uvijek nečujno. Prikazuje se na padajućoj traci i statusnoj traci."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Uvijek nečujno. Prikazuje se na padajućoj traci i zaključanom ekranu."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Uvijek nečujno. Prikazuje se na padajućoj traci, statusnoj traci i zaključanom ekranu."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Prikazuje se na padajućoj traci, statusnoj traci i zaključanom ekranu uz zvučno obavještenje."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Pomaže vam da se fokusirate prikazujući obavještenja samo na padajućoj traci. Uvijek nečujno."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Prikazuje se ispod prioritetnih obavještenja. Uvijek nečujno."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Prikazuje se ispod prioritetnih obavještenja. Uvijek nečujno."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Prikazuje se ispod prioritetnih obavještenja. Uvijek nečujno."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Privlači vašu pažnju pomoću zvuka i ikone na statusnoj traci. Prikazuje se na zaključanom ekranu."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Ta obavještenja se ne mogu izmijeniti."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Ovdje nije moguće konfigurirati ovu grupu obavještenja"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Obavještenje preko proksi servera"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Ova aplikacija koristi kameru."</string>
<string name="appops_microphone" msgid="741508267659494555">"Ova aplikacija koristi mikrofon."</string>
@@ -660,7 +668,7 @@
<string name="appops_mic_overlay" msgid="4835157962857919804">"Ova aplikacija prekriva druge aplikacije na ekranu i koristi mikrofon."</string>
<string name="appops_camera_mic_overlay" msgid="6718768197048030993">"Ova aplikacija prekriva druge aplikacije na ekranu i koristi mikrofon i kameru."</string>
<string name="notification_appops_settings" msgid="1028328314935908050">"Postavke"</string>
- <string name="notification_appops_ok" msgid="1156966426011011434">"UREDU"</string>
+ <string name="notification_appops_ok" msgid="1156966426011011434">"Uredu"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Otvorene su kontrole obavještenja za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Zatvorene su kontrole obavještenja za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Dozvoli obavještenja s ovog kanala"</string>
@@ -716,7 +724,7 @@
<string name="keyboard_key_numpad_template" msgid="8729216555174634026">"Numerička tastatura <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"Sistem"</string>
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Početak"</string>
- <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni ekrani"</string>
+ <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavno"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazad"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Obavještenja"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Prečice tastature"</string>
@@ -887,7 +895,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"Aplikacije koje rade u pozadini"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"Isključiti prijenos podataka na mobilnoj mreži?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"Nećete imati pristup podacima ili internetu preko mobilnog operatera <xliff:g id="CARRIER">%s</xliff:g>. Internet će biti dostupan samo preko WiFi mreže."</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"Nećete imati pristup podacima ili internetu putem mobilnog operatera <xliff:g id="CARRIER">%s</xliff:g>. Internet će biti dostupan samo putem WiFi mreže."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"vaš operater"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Postavke ne mogu potvrditi vaš odgovor jer aplikacija zaklanja zahtjev za odobrenje."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"Dozvoliti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> prikazivanje isječaka aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
@@ -916,8 +924,9 @@
<string name="music_controls_no_title" msgid="5236895307087002011">"Bez naslova"</string>
<string name="restart_button_description" msgid="2035077840254950187">"Dodirnite da ponovo pokrenete ovu aplikaciju i aktivirate prikaz preko cijelog ekrana."</string>
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Otvori aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="bubbles_settings_button_description" msgid="2970630476657287189">"Postavke za mjehuriće aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="bubbles_prompt" msgid="8807968030159469710">"Dozvoliti mjehuriće iz aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="bubbles_settings_button_description" msgid="2970630476657287189">"Postavke za oblačiće aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_prompt" msgid="8807968030159469710">"Dozvoliti oblačiće iz aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Upravljaj"</string>
<string name="no_bubbles" msgid="337101288173078247">"Odbij"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Dozvoli"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Pitaj me kasnije"</string>
@@ -928,4 +937,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Pomjerite gore desno"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Pomjeri dolje lijevo"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Pomjerite dolje desno"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index fdf34fa..a4f6fb4 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -178,7 +178,7 @@
<string name="data_connection_roaming" msgid="6037232010953697354">"Itinerància"</string>
<string name="data_connection_edge" msgid="871835227939216682">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
- <string name="accessibility_no_sim" msgid="8274017118472455155">"No hi ha cap targeta SIM."</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"No hi ha cap SIM."</string>
<string name="accessibility_cell_data" msgid="5326139158682385073">"Dades mòbils"</string>
<string name="accessibility_cell_data_on" msgid="5927098403452994422">"Dades mòbils activades"</string>
<string name="cell_data_off_content_description" msgid="4356113230238585072">"S\'han desactivat les dades mòbils"</string>
@@ -187,7 +187,7 @@
<string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Compartició de xarxa per Bluetooth"</string>
<string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode d\'avió."</string>
<string name="accessibility_vpn_on" msgid="5993385083262856059">"VPN activada"</string>
- <string name="accessibility_no_sims" msgid="3957997018324995781">"No hi ha cap targeta SIM."</string>
+ <string name="accessibility_no_sims" msgid="3957997018324995781">"No hi ha cap SIM."</string>
<string name="carrier_network_change_mode" msgid="8149202439957837762">"S\'està canviant la xarxa de l\'operador de telefonia mòbil"</string>
<string name="accessibility_battery_details" msgid="7645516654955025422">"Obre els detalls de la bateria"</string>
<string name="accessibility_battery_level" msgid="7451474187113371965">"<xliff:g id="NUMBER">%d</xliff:g> per cent de bateria."</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"S\'activarà a les <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Fins a les <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema fosc"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"L\'NFC està desactivada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"L\'NFC està activada"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"No ho tornis a mostrar"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Esborra-ho tot"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Gestió"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notificacions discretes"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Esborra totes les notificacions discretes"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificacions pausades pel mode No molestis"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Comença ara"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Cap notificació"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"La pantalla està fixada"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, toca i mantén premudes els botons Enrere i Aplicacions recents."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, mantén premuts els botons Enrere i Inici."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Aquest element es continuarà mostrant fins que deixis de fixar-lo. Llisca cap amunt i mantén premut per deixar de fixar-lo."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, toca i mantén premut el botó Aplicacions recents."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, mantén premut el botó d\'inici."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Per deixar de fixar aquesta pantalla, mantén premuts els botons Enrere i Aplicacions recents"</string>
@@ -637,15 +642,18 @@
<string name="inline_turn_off_notifications" msgid="8635596135532202355">"Desactiva les notificacions"</string>
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Vols continuar rebent notificacions d\'aquesta aplicació?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Discreta"</string>
- <string name="notification_alert_title" msgid="3966526305405016221">"Prioritària"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Sempre silenciosa. Es mostra a l\'àrea de notificacions."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Sempre silenciosa. Es mostra a l\'àrea de notificacions i la barra d\'estat."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Sempre silenciosa. Es mostra a l\'àrea de notificacions i la pantalla de bloqueig."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Sempre silenciosa. Es mostra a l\'àrea de notificacions, la barra d\'estat i la pantalla de bloqueig."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Emet un so i es mostra a l\'àrea de notificacions, la barra d\'estat i la pantalla de bloqueig."</string>
+ <string name="notification_alert_title" msgid="3966526305405016221">"Prioritàries"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"T\'ajuda a concentrar-te perquè les notificacions només es mostren a l\'àrea desplegable. Sempre en silenci."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Es mostra a sota de les notificacions prioritàries. Sempre en silenci."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Es mostra a sota de les notificacions prioritàries. Sempre en silenci."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Es mostra a sota de les notificacions prioritàries. Sempre en silenci."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Atrau la teva atenció amb un so i una icona a la barra d\'estat. Es mostra a la pantalla de bloqueig."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Aquestes notificacions no es poden modificar."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Aquest grup de notificacions no es pot configurar aquí"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notificació mitjançant aplicació intermediària"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Aquesta aplicació utilitza la càmera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Aquesta aplicació utilitza el micròfon."</string>
@@ -880,7 +888,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"Aplicacions que s\'estan executant en segon pla"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Toca per obtenir informació sobre l\'ús de dades i de bateria"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"Vols desactivar les dades mòbils?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"No tindràs accés a dades ni a Internet amb <xliff:g id="CARRIER">%s</xliff:g>. Només podràs accedir a Internet per Wi-Fi."</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"No tindràs accés a dades ni a Internet mitjançant <xliff:g id="CARRIER">%s</xliff:g>. Internet només estarà disponible per Wi-Fi."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"el teu operador de telefonia mòbil"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Com que hi ha una aplicació que oculta una sol·licitud de permís, no es pot verificar la teva resposta des de la configuració."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"Vols permetre que <xliff:g id="APP_0">%1$s</xliff:g> mostri porcions de l\'aplicació <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Obre <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Configuració de les bombolles: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Vols permetre les bombolles de l\'aplicació <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Gestiona"</string>
<string name="no_bubbles" msgid="337101288173078247">"Denega"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Permet"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Pregunta-m\'ho més tard"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Mou a dalt a la dreta"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Mou a baix a l\'esquerra"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Mou a baix a la dreta"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 9b0ea5c..9b2684f 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -39,7 +39,7 @@
<string name="battery_saver_start_action" msgid="8187820911065797519">"Zapnout spořič baterie"</string>
<string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nastavení"</string>
<string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
- <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Autom. otočení obrazovky"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Automatické otočení obrazovky"</string>
<string name="status_bar_settings_mute_label" msgid="554682549917429396">"ZTLUM."</string>
<string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
<string name="status_bar_settings_notifications" msgid="397146176280905137">"Oznámení"</string>
@@ -373,6 +373,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Zapnout v <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tmavé téma"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je vypnuto"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je zapnuto"</string>
@@ -454,6 +456,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Tuto zprávu příště nezobrazovat"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Smazat vše"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Spravovat"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Vlídná oznámení"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Vymazat všechna vlídná oznámení"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Oznámení jsou pozastavena režimem Nerušit"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Spustit"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Žádná oznámení"</string>
@@ -533,6 +537,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Obrazovka je připnuta"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Obsah bude připnut v zobrazení, dokud jej neuvolníte. Uvolníte jej stisknutím a podržením tlačítek Zpět a Přehled."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Obsah bude připnut v zobrazení, dokud ho neuvolníte. Uvolníte ho podržením tlačítek Zpět a Plocha."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Obsah bude připnut v zobrazení, dokud ho neuvolníte. Uvolnit ho můžete přejetím nahoru a podržením."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Obsah bude připnut v zobrazení, dokud jej neuvolníte. Uvolníte jej stisknutím a podržením tlačítka Přehled."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Obsah bude připnut v zobrazení, dokud ho neuvolníte. Uvolníte ho podržením tlačítka Plocha."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Chcete-li tuto obrazovku uvolnit, podržte tlačítka Zpět a Přehled"</string>
@@ -594,7 +599,7 @@
<string name="zen_alarm_warning_indef" msgid="3482966345578319605">"Pokud tento režim nevypnete, svůj další budík <xliff:g id="WHEN">%1$s</xliff:g> neuslyšíte"</string>
<string name="zen_alarm_warning" msgid="444533119582244293">"Svůj další budík <xliff:g id="WHEN">%1$s</xliff:g> neuslyšíte"</string>
<string name="alarm_template" msgid="3980063409350522735">"v <xliff:g id="WHEN">%1$s</xliff:g>"</string>
- <string name="alarm_template_far" msgid="4242179982586714810">"dne <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+ <string name="alarm_template_far" msgid="4242179982586714810">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="accessibility_quick_settings_detail" msgid="2579369091672902101">"Rychlé nastavení <xliff:g id="TITLE">%s</xliff:g>."</string>
<string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Hotspot"</string>
<string name="accessibility_managed_profile" msgid="6613641363112584120">"Pracovní profil"</string>
@@ -644,14 +649,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Mají se oznámení z této aplikace nadále zobrazovat?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Nenápadná"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritní"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Vždy tichý režim. Zobrazí se na vysouvacím panelu."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Vždy tichý režim. Zobrazí se na vysouvacím panelu a stavovém řádku."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Vždy tichý režim. Zobrazí se na vysouvacím panelu a obrazovce uzamčení."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Vždy tichý režim. Zobrazí se na vysouvacím panelu, stavovém řádku a obrazovce uzamčení."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Vydá zvuk a zobrazí se na vysouvacím panelu, stavovém řádku a obrazovce uzamčení."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Budete se moci lépe soustředit, protože oznámení se budou zobrazovat pouze na vysouvacím panelu. Vždy tichý režim."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Níže zobrazit prioritní oznámení. Vždy tichý režim."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Níže zobrazit prioritní oznámení. Vždy tichý režim."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Níže zobrazit prioritní oznámení. Vždy tichý režim."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Upozorní vás pomocí zvuku a ikony na stavovém řádku. Zobrazit na obrazovce uzamčení."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Tato oznámení nelze upravit."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Tuto skupinu oznámení tady nelze nakonfigurovat"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Zprostředkované oznámení"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Tato aplikace využívá fotoaparát."</string>
<string name="appops_microphone" msgid="741508267659494555">"Tato aplikace využívá mikrofon."</string>
@@ -921,6 +929,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Otevřít <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Nastavení bublin aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Povolit bubliny z aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Spravovat"</string>
<string name="no_bubbles" msgid="337101288173078247">"Zakázat"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Povolit"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Zeptat se později"</string>
@@ -931,4 +940,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Přesunout vpravo nahoru"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Přesunout vlevo dolů"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Přesunout vpravo dolů"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 53e47bb..61b9fff 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Tænd kl. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Indtil <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Mørkt tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC er deaktiveret"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC er aktiveret"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Vis ikke igen"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Ryd alt"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Administrer"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Diskrete underretninger"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Ryd alle diskrete notifikationer"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifikationer er sat på pause af Forstyr ikke"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Start nu"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Ingen notifikationer"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Skærmen er fastgjort"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Dette fastholder skærmen i visningen, indtil du frigør den. Tryk på Tilbage og Overblik, og hold fingeren nede for at frigøre skærmen."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Dette fastholder skærmen i visningen, indtil du frigør den. Hold Tilbage og Startskærm nede for at frigøre skærmen."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Dette fastholder skærmen i visningen, indtil du frigør den. Stryg opad, og hold fingeren nede for at frigøre den."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Dette fastholder skærmen i visningen, indtil du frigør den. Tryk på Tilbage, og hold fingeren nede for at frigøre skærmen."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Dette fastholder skærmen i visningen, indtil du frigør den. Hold Startskærm nede for at frigøre skærmen."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Hold knapperne Tilbage og Oversigt nede for at frigøre skærmen"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Vil du fortsætte med at se notifikationer fra denne app?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Diskret"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioriteret"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Altid lydløs. Vises i panelet, der trækkes ned."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Altid lydløs. Vises i panelet, der trækkes ned, og i statusbjælken."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Altid lydløs. Vises i panelet, der trækkes ned, og på låseskærmen"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Altid lydløs. Vises i panelet, der trækkes ned, i statusbjælken og på låseskærmen."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Laver lyd og vises i panelet, der trækkes ned, i statusbjælken og på låseskærmen."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Hjælper dig med at fokusere på de vigtige ting, da notifikationerne kun vises i panelet, der trækkes ned. Altid lydløs."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Viser notifikationer med lav prioritet. Altid lydløs."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Viser notifikationer med lav prioritet. Altid lydløs."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Viser notifikationer med lav prioritet. Altid lydløs."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Fanger din opmærksomhed med lyd og ikoner i statusbjælken. Vises på låseskærmen."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Disse notifikationer kan ikke redigeres."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Du kan ikke konfigurere denne gruppe notifikationer her"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Proxyforbundet notifikation"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Denne app anvender kameraet."</string>
<string name="appops_microphone" msgid="741508267659494555">"Denne app anvender mikrofonen."</string>
@@ -718,7 +726,7 @@
<string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistance"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakter"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Mail"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="638701213803242744">"Sms"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musik"</string>
<string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Åbn <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Indstillinger for <xliff:g id="APP_NAME">%1$s</xliff:g>-bobler"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Vil du tillade bobler fra <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Administrer"</string>
<string name="no_bubbles" msgid="337101288173078247">"Afvis"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Tillad"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Spørg mig senere"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Flyt op til højre"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Flyt ned til venstre"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Flyt ned til højre"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 8e26985..604a576 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -373,6 +373,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"An um <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Bis <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Dunkles Design"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ist deaktiviert"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ist aktiviert"</string>
@@ -452,6 +454,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Nicht mehr anzeigen"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Alle löschen"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Verwalten"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Stumme Benachrichtigungen"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Alle stummen Benachrichtigungen löschen"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Benachrichtigungen durch \"Bitte nicht stören\" pausiert"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Jetzt starten"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Keine Benachrichtigungen"</string>
@@ -531,6 +535,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Bildschirm ist fixiert"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Der Bildschirm bleibt so lange eingeblendet, bis du die Fixierung aufhebst. Berühre und halte dazu \"Zurück\" und \"Übersicht\"."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Der Bildschirm wird so lange angezeigt, bis du die Fixierung aufhebst. Berühre und halte dazu \"Zurück\" und \"Startbildschirm\"."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Der Bildschirm wird so lange angezeigt, bis du die Fixierung aufhebst. Dazu wischst du nach oben und hältst den Bildschirm gedrückt"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Der Bildschirm bleibt so lange eingeblendet, bis du die Fixierung aufhebst. Berühre und halte dazu \"Übersicht\"."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Der Bildschirm wird so lange angezeigt, bis du die Fixierung aufhebst. Berühre und halte dazu \"Startbildschirm\"."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Um die Fixierung für diesen Bildschirm aufzuheben, berühre und halte \"Zurück\" und \"Übersicht\""</string>
@@ -642,14 +647,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Benachrichtigungen dieser App weiterhin anzeigen?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Stumm"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Priorisiert"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Immer lautlos. Benachrichtigungen erscheinen in der Benachrichtigungsleiste."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Immer lautlos. Benachrichtigungen erscheinen in der Benachrichtigungsleiste und der Statusleiste."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Immer lautlos. Benachrichtigungen erscheinen in der Benachrichtigungsleiste und auf dem Sperrbildschirm."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Immer lautlos. Benachrichtigungen erscheinen in der Benachrichtigungsleiste, der Statusleiste und auf dem Sperrbildschirm."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Akustisches Signal ertönt. Benachrichtigungen erscheinen in der Benachrichtigungsleiste, der Statusleiste und auf dem Sperrbildschirm."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Benachrichtigungen erscheinen nur in der Benachrichtigungsleiste. So kannst du dich besser konzentrieren. Immer lautlos."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Erscheinen unter den wichtigen Benachrichtigungen. Immer lautlos."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Erscheinen unter den wichtigen Benachrichtigungen. Immer lautlos."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Erscheinen unter den wichtigen Benachrichtigungen. Immer lautlos."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Benachrichtigungen werden mit einem Ton und einem Statusleistensymbol angekündigt. Erscheinen auf dem Sperrbildschirm."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Diese Benachrichtigungen können nicht geändert werden."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Die Benachrichtigungsgruppe kann hier nicht konfiguriert werden"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Weitergeleitete Benachrichtigung"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Diese App verwendet die Kamera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Diese App verwendet das Mikrofon."</string>
@@ -915,6 +923,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> öffnen"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Einstellungen für <xliff:g id="APP_NAME">%1$s</xliff:g>-Bubbles"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g>-Bubbles zulassen?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Verwalten"</string>
<string name="no_bubbles" msgid="337101288173078247">"Ablehnen"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Zulassen"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Später fragen"</string>
@@ -925,4 +934,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Nach rechts oben verschieben"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Nach unten links verschieben"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Nach unten rechts verschieben"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 39ba9a4..130934f 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ενεργοποίηση στις <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Έως τις <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Σκούρο θέμα"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Το NFC είναι απενεργοποιημένο"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Το NFC είναι ενεργοποιημένο"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Να μην εμφανιστεί ξανά"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Διαγραφή όλων"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Διαχείριση"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Διακριτικές ειδοποιήσεις"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Καταργήστε όλες τις διακριτικές ειδοποιήσεις"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Οι ειδοποιήσεις τέθηκαν σε παύση από τη λειτουργία \"Μην ενοχλείτε\""</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Έναρξη τώρα"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Δεν υπάρχουν ειδοποιήσεις"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Η οθόνη καρφιτσώθηκε"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Με αυτόν τον τρόπο παραμένει σε προβολή μέχρι να το ξεκαρφιτσώσετε. Αγγίξτε παρατεταμένα τα στοιχεία \"Επιστροφή\" και \"Επισκόπηση\" για ξεκαρφίτσωμα."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Με αυτόν τον τρόπο, παραμένει σε προβολή μέχρι να το ξεκαρφιτσώσετε. Αγγίξτε παρατεταμένα τα στοιχεία \"Πίσω\" και \"Αρχική οθόνη\" για ξεκαρφίτσωμα."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Με αυτόν τον τρόπο, παραμένει σε προβολή μέχρι να το ξεκαρφιτσώσετε. Σύρετε προς τα επάνω και κρατήστε πατημένο το δάχτυλό σας για ξεκαρφίτσωμα."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Με αυτόν τον τρόπο παραμένει σε προβολή μέχρι να το ξεκαρφιτσώσετε. Αγγίξτε παρατεταμένα την \"Επισκόπηση\" για ξεκαρφίτσωμα."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Με αυτόν τον τρόπο, παραμένει σε προβολή μέχρι να το ξεκαρφιτσώσετε. Αγγίξτε παρατεταμένα το στοιχείο \"Αρχική οθόνη\" για ξεκαρφίτσωμα."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Για να ξεκαρφιτσώσετε αυτήν την οθόνη, αγγίξτε παρατεταμένα τα κουμπιά \"Πίσω\" και \"Επισκόπηση\""</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Να συνεχίσουν να εμφανίζονται ειδοποιήσεις από αυτήν την εφαρμογή;"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Διακριτικές"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Προτεραιότητας"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Σίγαση πάντα. Εμφανίζεται στο αναπτυσσόμενο πλαίσιο."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Σίγαση πάντα. Εμφανίζεται στο αναπτυσσόμενο πλαίσιο σκίασης και τη γραμμή κατάστασης."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Σίγαση πάντα. Εμφανίζεται στο αναπτυσσόμενο πλαίσιο σκίασης και την οθόνη κλειδώματος."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Σίγαση πάντα. Εμφανίζεται στο αναπτυσσόμενο πλαίσιο σκίασης, τη γραμμή κατάστασης και την οθόνη κλειδώματος."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Παράγει ήχο και εμφανίζεται στο αναπτυσσόμενο πλαίσιο σκίασης, τη γραμμή κατάστασης και την οθόνη κλειδώματος."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Σας βοηθάει να συγκεντρωθείτε με ειδοποιήσεις που εμφανίζονται μόνο στο αναπτυσσόμενο πλαίσιο σκίασης. Πάντα σε σίγαση."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Εμφανίζεται κάτω από ειδοποιήσεις προτεραιότητας. Πάντα σε σίγαση."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Εμφανίζεται κάτω από ειδοποιήσεις προτεραιότητας. Πάντα σε σίγαση."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Εμφανίζεται κάτω από ειδοποιήσεις προτεραιότητας. Πάντα σε σίγαση."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Τραβάει την προσοχή σας με ήχους και ένα εικονίδιο γραμμής κατάστασης. Εμφανίζεται στην οθόνη κλειδώματος."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Δεν είναι δυνατή η τροποποίηση αυτών των ειδοποιήσεων"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Δεν είναι δυνατή η διαμόρφωση αυτής της ομάδας ειδοποιήσεων εδώ"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Ειδοποίηση μέσω διακομιστή μεσολάβησης"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Αυτή η εφαρμογή χρησιμοποιεί την κάμερα."</string>
<string name="appops_microphone" msgid="741508267659494555">"Αυτή η εφαρμογή χρησιμοποιεί το μικρόφωνο."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Άνοιγμα <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Ρυθμίσεις για συννεφάκια <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Να επιτρέπονται συννεφάκια από την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Διαχείριση"</string>
<string name="no_bubbles" msgid="337101288173078247">"Όχι"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Να επιτρέπεται"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Να ερωτηθώ αργότερα"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Μετακίνηση επάνω δεξιά"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Μετακίνηση κάτω αριστερά"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Μετακίνηση κάτω δεξιά"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index ec4afed..e047482 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Dark Theme"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Don\'t show again"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Clear all"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Manage"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Gentle notifications"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Clear all gentle notifications"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifications paused by Do Not Disturb"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Start now"</string>
<string name="empty_shade_text" msgid="708135716272867002">"No notifications"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Screen is pinned"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"This keeps it in view until you unpin. Swipe up & hold to unpin."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"This keeps it in view until you unpin. Touch & hold Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"To unpin this screen, touch & hold Back and Overview buttons"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Gentle"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritised"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Always silent. Displays in pull-down shade."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Always silent. Displays in pull-down shade & status bar."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Always silent. Displays in pull-down shade & on lock screen."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Always silent. Displays in pull-down shade, status bar & on lock screen."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Makes sound and displays in pull-down shade, status bar & on lock screen."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Helps you focus with notifications only in the pull-down shade. Always silent."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Gets your attention with sound and a status bar icon. Shows on lock screen."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"These notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"This group of notifications cannot be configured here"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Proxied notification"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"This app is using the camera."</string>
<string name="appops_microphone" msgid="741508267659494555">"This app is using the microphone."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Open <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Settings for <xliff:g id="APP_NAME">%1$s</xliff:g> bubbles"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Allow bubbles from <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Manage"</string>
<string name="no_bubbles" msgid="337101288173078247">"Deny"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Allow"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Ask me later"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Move top right"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Move bottom left"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Move bottom right"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 2bc1799..a55615f 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Dark Theme"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Don\'t show again"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Clear all"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Manage"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Gentle notifications"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Clear all gentle notifications"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifications paused by Do Not Disturb"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Start now"</string>
<string name="empty_shade_text" msgid="708135716272867002">"No notifications"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Screen is pinned"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"This keeps it in view until you unpin. Swipe up & hold to unpin."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"This keeps it in view until you unpin. Touch & hold Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"To unpin this screen, touch & hold Back and Overview buttons"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Gentle"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritised"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Always silent. Displays in pull-down shade."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Always silent. Displays in pull-down shade & status bar."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Always silent. Displays in pull-down shade & on lock screen."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Always silent. Displays in pull-down shade, status bar & on lock screen."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Makes sound and displays in pull-down shade, status bar & on lock screen."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Helps you focus with notifications only in the pull-down shade. Always silent."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Gets your attention with sound and a status bar icon. Shows on lock screen."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"These notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"This group of notifications cannot be configured here"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Proxied notification"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"This app is using the camera."</string>
<string name="appops_microphone" msgid="741508267659494555">"This app is using the microphone."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Open <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Settings for <xliff:g id="APP_NAME">%1$s</xliff:g> bubbles"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Allow bubbles from <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Manage"</string>
<string name="no_bubbles" msgid="337101288173078247">"Deny"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Allow"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Ask me later"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Move top right"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Move bottom left"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Move bottom right"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index ec4afed..e047482 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Dark Theme"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Don\'t show again"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Clear all"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Manage"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Gentle notifications"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Clear all gentle notifications"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifications paused by Do Not Disturb"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Start now"</string>
<string name="empty_shade_text" msgid="708135716272867002">"No notifications"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Screen is pinned"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"This keeps it in view until you unpin. Swipe up & hold to unpin."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"This keeps it in view until you unpin. Touch & hold Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"To unpin this screen, touch & hold Back and Overview buttons"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Gentle"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritised"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Always silent. Displays in pull-down shade."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Always silent. Displays in pull-down shade & status bar."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Always silent. Displays in pull-down shade & on lock screen."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Always silent. Displays in pull-down shade, status bar & on lock screen."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Makes sound and displays in pull-down shade, status bar & on lock screen."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Helps you focus with notifications only in the pull-down shade. Always silent."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Gets your attention with sound and a status bar icon. Shows on lock screen."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"These notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"This group of notifications cannot be configured here"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Proxied notification"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"This app is using the camera."</string>
<string name="appops_microphone" msgid="741508267659494555">"This app is using the microphone."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Open <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Settings for <xliff:g id="APP_NAME">%1$s</xliff:g> bubbles"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Allow bubbles from <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Manage"</string>
<string name="no_bubbles" msgid="337101288173078247">"Deny"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Allow"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Ask me later"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Move top right"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Move bottom left"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Move bottom right"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index ec4afed..e047482 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Dark Theme"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Don\'t show again"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Clear all"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Manage"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Gentle notifications"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Clear all gentle notifications"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifications paused by Do Not Disturb"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Start now"</string>
<string name="empty_shade_text" msgid="708135716272867002">"No notifications"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Screen is pinned"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"This keeps it in view until you unpin. Swipe up & hold to unpin."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"This keeps it in view until you unpin. Touch & hold Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"To unpin this screen, touch & hold Back and Overview buttons"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Gentle"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritised"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Always silent. Displays in pull-down shade."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Always silent. Displays in pull-down shade & status bar."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Always silent. Displays in pull-down shade & on lock screen."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Always silent. Displays in pull-down shade, status bar & on lock screen."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Makes sound and displays in pull-down shade, status bar & on lock screen."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Helps you focus with notifications only in the pull-down shade. Always silent."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Gets your attention with sound and a status bar icon. Shows on lock screen."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"These notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"This group of notifications cannot be configured here"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Proxied notification"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"This app is using the camera."</string>
<string name="appops_microphone" msgid="741508267659494555">"This app is using the microphone."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Open <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Settings for <xliff:g id="APP_NAME">%1$s</xliff:g> bubbles"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Allow bubbles from <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Manage"</string>
<string name="no_bubbles" msgid="337101288173078247">"Deny"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Allow"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Ask me later"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Move top right"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Move bottom left"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Move bottom right"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index e771489..7aa44bf 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -369,6 +369,7 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Dark Theme"</string>
+ <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="3496696903886673256">"Dark Theme\nBattery saver"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -448,6 +449,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Don\'t show again"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Clear all"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Manage"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Gentle notifications"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Clear all gentle notifications"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifications paused by Do Not Disturb"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Start now"</string>
<string name="empty_shade_text" msgid="708135716272867002">"No notifications"</string>
@@ -527,6 +530,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Screen is pinned"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"This keeps it in view until you unpin. Swipe up & hold to unpin."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"This keeps it in view until you unpin. Touch & hold Overview to unpin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"To unpin this screen, touch & hold Back and Overview buttons"</string>
@@ -638,14 +642,16 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Gentle"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritized"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Always silent. Displays in pull-down shade."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Always silent. Displays in pull-down shade & status bar."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Always silent. Displays in pull-down shade & on lock screen."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Always silent. Displays in pull-down shade, status bar & on lock screen."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Makes sound and displays in pull-down shade, status bar & on lock screen."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Helps you focus with notifications only in the pull-down shade. Always silent."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Displays below priority notifications. Always silent."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Gets your attention with sound & a status bar icon. Shows on lock screen."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"These notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"This group of notifications cannot be configured here"</string>
<string name="notification_delegate_header" msgid="2857691673814814270">"Proxied notification"</string>
+ <string name="notification_channel_dialog_title" msgid="5745335243729167866">"All <xliff:g id="APP_NAME">%1$s</xliff:g> notifications"</string>
+ <string name="see_more_title" msgid="5358726697042112726">"See more"</string>
<string name="appops_camera" msgid="8100147441602585776">"This app is using the camera."</string>
<string name="appops_microphone" msgid="741508267659494555">"This app is using the microphone."</string>
<string name="appops_overlay" msgid="6165912637560323464">"This app is displaying over other apps on your screen."</string>
@@ -910,6 +916,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Open <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Settings for <xliff:g id="APP_NAME">%1$s</xliff:g> bubbles"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Allow bubbles from <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Manage"</string>
<string name="no_bubbles" msgid="337101288173078247">"Deny"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Allow"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Ask me later"</string>
@@ -920,4 +927,5 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Move top right"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Move bottom left"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Move bottom right"</string>
+ <string name="bubble_dismiss_text" msgid="8028337712674081668">"Dismiss"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index ba27321..95fcbe5 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"A la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Hasta <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema oscuro"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"La tecnología NFC está inhabilitada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"La tecnología NFC está habilitada"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"No volver a mostrar"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Borrar todo"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Administrar"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notificaciones discretas"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Borrar todas las notificaciones discretas"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificaciones pausadas por el modo \"No interrumpir\""</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Comenzar ahora"</string>
<string name="empty_shade_text" msgid="708135716272867002">"No hay notificaciones"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Pantalla fija"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Esta función mantiene la pantalla visible hasta que dejes de fijarla. Para ello, mantén presionados los botones Atrás y Recientes."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Esta función mantiene la pantalla visible hasta que dejes de fijarla. Para ello, mantén presionados los botones de inicio y Atrás."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Esta función mantiene la pantalla visible hasta que dejes de fijarla. Desliza el dedo hacia arriba y mantén presionado para dejar de fijarla."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Esta función mantiene la pantalla visible hasta que dejes de fijarla. Para ello, mantén presionado el botón Recientes."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Esta función mantiene la pantalla visible hasta que dejes de fijarla. Para ello, mantén presionado el botón de inicio."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Para dejar de fijar esta pantalla, mantén presionados los botones Atrás y Recientes"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"¿Quieres seguir viendo las notificaciones de esta app?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Silenciosa"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritaria"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Siempre en silencio. Se muestra en un banner desplegable."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Siempre en silencio. Se muestra en un banner desplegable y la barra de estado."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Siempre en silencio. Se muestra en un banner desplegable y la pantalla bloqueada."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Siempre en silencio. Se muestra en un banner desplegable, la barra de estado y la pantalla bloqueada."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Reproduce sonido y se muestra en un banner desplegable, la barra de estado y la pantalla bloqueada."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Te ayuda a concentrarte, ya que las notificaciones se muestran solo como banner desplegable. Siempre en silencio."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Se muestra debajo de las notificaciones de prioridad. Siempre en silencio."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Se muestra debajo de las notificaciones de prioridad. Siempre en silencio."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Se muestra debajo de las notificaciones de prioridad. Siempre en silencio."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Capta tu atención con un sonido y un ícono en la barra de estado. Se muestra en la pantalla bloqueada."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"No se pueden modificar estas notificaciones."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"No se puede configurar aquí este grupo de notificaciones"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notificación almacenada en proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Esta app está usando la cámara."</string>
<string name="appops_microphone" msgid="741508267659494555">"Esta app está usando el micrófono."</string>
@@ -712,7 +720,7 @@
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recientes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atrás"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificaciones"</string>
- <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Combinación de teclas"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Ver combinaciones de teclas"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="8413348767825486492">"Cambiar diseño del teclado"</string>
<string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicaciones"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistencia"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Abrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Configuración para cuadros de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"¿Quieres permitir cuadros de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Administrar"</string>
<string name="no_bubbles" msgid="337101288173078247">"Denegar"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Permitir"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Preguntarme más tarde"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Ubicar arriba a la derecha"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Ubicar abajo a la izquierda"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Ubicar abajo a la derecha"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 2788c41..a55b4d6 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -367,8 +367,10 @@
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Al atardecer"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Hasta el amanecer"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Hora: <xliff:g id="TIME">%s</xliff:g>"</string>
- <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Hasta: <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Hasta las <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema oscuro"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"La conexión NFC está inhabilitada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"La conexión NFC está habilitada"</string>
@@ -418,7 +420,7 @@
<string name="guest_new_guest" msgid="600537543078847803">"Añadir invitado"</string>
<string name="guest_exit_guest" msgid="7187359342030096885">"Quitar invitado"</string>
<string name="guest_exit_guest_dialog_title" msgid="8480693520521766688">"¿Quitar invitado?"</string>
- <string name="guest_exit_guest_dialog_message" msgid="4155503224769676625">"Se eliminarán las aplicaciones y los datos de esta sesión."</string>
+ <string name="guest_exit_guest_dialog_message" msgid="4155503224769676625">"Se eliminarán todas las aplicaciones y datos de esta sesión."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7402231963862520531">"Quitar"</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"Hola de nuevo, invitado"</string>
<string name="guest_wipe_session_message" msgid="8476238178270112811">"¿Quieres continuar con la sesión?"</string>
@@ -438,7 +440,7 @@
<item quantity="one">Solo se puede crear un usuario.</item>
</plurals>
<string name="user_remove_user_title" msgid="4681256956076895559">"¿Quitar usuario?"</string>
- <string name="user_remove_user_message" msgid="1453218013959498039">"Se eliminarán todas las aplicaciones y todos los datos de este usuario."</string>
+ <string name="user_remove_user_message" msgid="1453218013959498039">"Se eliminarán todas las aplicaciones y datos de este usuario."</string>
<string name="user_remove_user_remove" msgid="7479275741742178297">"Quitar"</string>
<string name="battery_saver_notification_title" msgid="8614079794522291840">"Ahorro de batería activado"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduce el rendimiento y los datos en segundo plano"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"No volver a mostrar"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Borrar todo"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Gestionar"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notificaciones discretas"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Borrar todas las notificaciones discretas"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificaciones pausadas por el modo No molestar"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Iniciar ahora"</string>
<string name="empty_shade_text" msgid="708135716272867002">"No hay notificaciones"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Pantalla fijada"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"La pantalla se mantiene visible hasta que dejas de fijarla. Para ello, mantén pulsados los botones Atrás y Aplicaciones recientes."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"La pantalla se mantiene visible hasta que dejas de fijarla. Para ello, mantén pulsados los botones Atrás e Inicio."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Se mantiene visible hasta que dejas de fijarla. Para ello, desliza el dedo hacia arriba y mantén pulsado."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"La pantalla se mantiene visible hasta que dejas de fijarla. Para ello, mantén pulsado el botón Aplicaciones recientes."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"La pantalla se mantiene visible hasta que dejas de fijarla. Para ello, mantén pulsado el botón Inicio."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Mantén pulsado el botón Atrás y el de aplicaciones recientes para dejar de fijar esta pantalla"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"¿Quieres seguir viendo las notificaciones de esta aplicación?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Discretas"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Priorizadas"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Siempre en silencio. Se muestra en la pantalla desplegable."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Siempre en silencio. Se muestra en la pantalla desplegable y en la barra de estado."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Siempre en silencio. Se muestra en la pantalla desplegable y en la pantalla de bloqueo."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Siempre en silencio. Se muestra en el desplegable, la barra de estado y la pantalla de bloqueo."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Emite un sonido y se muestra en el desplegable, en la barra de estado y en la pantalla de bloqueo."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Las notificaciones solo se muestran en la pantalla desplegable para que puedas concentrarte. Siempre en silencio."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Muestra las notificaciones con prioridad baja. Siempre en silencio."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Muestra las notificaciones con prioridad baja. Siempre en silencio."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Muestra las notificaciones con prioridad baja. Siempre en silencio."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Atrae tu atención a través del sonido y el icono en la barra de estado. Se muestra en la pantalla de bloqueo."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Estas notificaciones no se pueden modificar."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Este grupo de notificaciones no se puede configurar aquí"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notificación mediante proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Esta aplicación está usando la cámara."</string>
<string name="appops_microphone" msgid="741508267659494555">"Esta aplicación está usando el micrófono."</string>
@@ -712,7 +720,7 @@
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recientes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atrás"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificaciones"</string>
- <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Combinaciones de teclas"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Ver combinaciones de teclas"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="8413348767825486492">"Cambiar diseño del teclado"</string>
<string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicaciones"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistencia"</string>
@@ -766,7 +774,7 @@
<string name="left_icon" msgid="3096287125959387541">"Icono a la izquierda"</string>
<string name="right_icon" msgid="3952104823293824311">"Icono a la derecha"</string>
<string name="drag_to_add_tiles" msgid="230586591689084925">"Pulsa y arrastra para añadir funciones"</string>
- <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Mantén pulsado un icono y arrástralo para reorganizarlo"</string>
+ <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Mantén pulsado un icono y arrástralo para reubicarlo"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastra aquí para quitar una función"</string>
<string name="drag_to_remove_disabled" msgid="2390968976638993382">"Necesitas al menos 6 iconos"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
@@ -880,7 +888,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"Aplicaciones que se están ejecutando en segundo plano"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Toca para ver información detallada sobre el uso de datos y de la batería"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"¿Quieres desactivar los datos móviles?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"No tienes conexión a Internet ni de datos móviles a través de <xliff:g id="CARRIER">%s</xliff:g>. Solo puedes conectarte a Internet mediante una red Wi‑Fi."</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"No tendrás conexión a Internet ni de datos móviles a través de <xliff:g id="CARRIER">%s</xliff:g>. Solo podrás conectarte a Internet mediante una red Wi‑Fi."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"tu operador"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Una aplicación impide ver una solicitud de permiso, por lo que Ajustes no puede verificar tu respuesta."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"¿Quieres permitir que <xliff:g id="APP_0">%1$s</xliff:g> muestre fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Abrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Ajustes de las burbujas de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"¿Quieres permitir las burbujas de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Gestionar"</string>
<string name="no_bubbles" msgid="337101288173078247">"Denegar"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Permitir"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Preguntarme más tarde"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Mover arriba a la derecha"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Mover abajo a la izquierda."</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Mover abajo a la derecha"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 8f78718..b03fb6b7 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Sisselülitam. kell <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Kuni <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tume teema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC on keelatud"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC on lubatud"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ära kuva uuesti"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Tühjenda kõik"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Haldamine"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Leebed märguanded"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Kustuta kõik leebed märguanded"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Režiim Mitte segada peatas märguanded"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Alusta kohe"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Märguandeid pole"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekraan on kinnitatud"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"See hoitakse kuval, kuni selle vabastate. Vabastamiseks puudutage pikalt nuppe Tagasi ja Ülevaade."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"See hoitakse kuval, kuni selle vabastate. Vabastamiseks puudutage pikalt nuppe Tagasi ja Avakuva."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"See hoitakse kuval, kuni selle vabastate. Vabastamiseks pühkige üles ja hoidke sõrme ekraanil."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"See hoitakse kuval, kuni selle vabastate. Vabastamiseks puudutage pikalt nuppu Ülevaade."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"See hoitakse kuval, kuni selle vabastate. Vabastamiseks puudutage pikalt nuppu Avakuva."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Ekraanikuva vabastamiseks puudutage pikalt nuppe Tagasi ja Ülevaade"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Kas jätkata selle rakenduse märguannete kuvamist?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Leebe"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioriseeritud"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Alati vaikne. Kuvatakse allatõmmatavas menüüs."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Alati vaikne. Kuvatakse allatõmmatavas menüüs ja olekuribal."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Alati vaikne. Kuvatakse allatõmmatavas menüüs ja lukustuskuval."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Alati vaikne. Kuvatakse allatõmmatavas menüüs, olekuribal ja lukustuskuval."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Kostub heli, kuvatakse allatõmmatavas menüüs, olekuribal ja lukustuskuval."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Aitab teil allatõmmatavas menüüs ainult märguannetele keskenduda. Alati vaikne."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Kuvatakse prioriteetsete märguannete all. Alati vaikne."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Kuvatakse prioriteetsete märguannete all. Alati vaikne."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Kuvatakse prioriteetsete märguannete all. Alati vaikne."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Haarab teie tähelepanu heli ja olekuriba ikooni abil. Kuvatakse lukustuskuval."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Neid märguandeid ei saa muuta."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Seda märguannete rühma ei saa siin seadistada"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Puhvriga märguanne"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"See rakendus kasutab kaamerat."</string>
<string name="appops_microphone" msgid="741508267659494555">"See rakendus kasutab mikrofoni."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Ava <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> mullide seaded"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Kas soovite rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> mullid lubada?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Halda"</string>
<string name="no_bubbles" msgid="337101288173078247">"Keela"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Luba"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Küsi hiljem"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Teisalda üles paremale"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Teisalda alla vasakule"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Teisalda alla paremale"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 448eb4e..33ab838 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Aktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> arte"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Gai iluna"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Desgaituta dago NFC"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Gaituta dago NFC"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ez erakutsi berriro"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Garbitu guztiak"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Kudeatu"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Soinurik gabeko jakinarazpenak"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Garbitu soinurik gabeko jakinarazpen guztiak"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\"Ez molestatu\" moduak pausatu egin ditu jakinarazpenak"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Hasi"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Ez dago jakinarazpenik"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Pantaila ainguratuta dago"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta \"Atzera\" eta \"Ikuspegi orokorra\" botoiak."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta Atzera eta Hasiera botoiak."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta Hasiera botoia."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta \"Ikuspegi orokorra\" botoia."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta Hasiera botoia."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Pantailari aingura kentzeko, eduki sakatuta Atzera eta Ikuspegi orokorra botoiak"</string>
@@ -637,15 +642,18 @@
<string name="inline_turn_off_notifications" msgid="8635596135532202355">"Desaktibatu jakinarazpenak"</string>
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Aplikazio honen jakinarazpenak erakusten jarraitzea nahi duzu?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Jakinarazi soinurik gabe"</string>
- <string name="notification_alert_title" msgid="3966526305405016221">"Lehentasunezkoa"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Beti isilik. Jakinarazpenen panelean bistaratzen da."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Beti isilik. Jakinarazpenen panelean eta egoera-barran bistaratzen da."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Beti isilik. Jakinarazpenen panelean eta pantaila blokeatuan bistaratzen da."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Beti isilik. Jakinarazpenen panelean, egoera-barran eta pantaila blokeatuan bistaratzen da."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Soinua jotzen du, eta jakinarazpenen panelean, egoera-barran eta pantaila blokeatuan bistaratzen da."</string>
+ <string name="notification_alert_title" msgid="3966526305405016221">"Lehentasunezkoak"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Pantailaren goialdeko goitibeherako barran bakarrik erakusten ditu jakinarazpenak, arretarik gal ez dezazun. Beti isilik."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Lehentasunik ez duten jakinarazpenak erakusten ditu. Beti isilik."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Lehentasunik ez duten jakinarazpenak erakusten ditu. Beti isilik."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Lehentasunik ez duten jakinarazpenak erakusten ditu. Beti isilik."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Arretari dei egiten dio soinua eginda eta egoera-barran ikonoa erakutsita. Pantaila blokeatua agertzen da."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Jakinarazpen horiek ezin dira aldatu."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Jakinarazpen talde hau ezin da konfiguratu hemen"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Proxy bidezko jakinarazpena"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Kamera erabiltzen ari da aplikazioa."</string>
<string name="appops_microphone" msgid="741508267659494555">"Mikrofonoa erabiltzen ari da aplikazioa."</string>
@@ -765,8 +773,8 @@
<string name="right_keycode" msgid="708447961000848163">"Eskuineko teklaren kodea"</string>
<string name="left_icon" msgid="3096287125959387541">"Ezkerreko ikonoa"</string>
<string name="right_icon" msgid="3952104823293824311">"Eskuineko ikonoa"</string>
- <string name="drag_to_add_tiles" msgid="230586591689084925">"Eduki sakatuta eta arrastatu lauzak gehitzeko"</string>
- <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Eduki sakatuta eta arrastatu, lauzak berrantolatzeko"</string>
+ <string name="drag_to_add_tiles" msgid="230586591689084925">"Lauzak gehitzeko, eduki sakatuta eta arrastatu"</string>
+ <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Lauzak antolatzeko, eduki sakatuta eta arrastatu"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"Kentzeko, arrastatu hona"</string>
<string name="drag_to_remove_disabled" msgid="2390968976638993382">"Gutxienez sei lauza behar dituzu"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editatu"</string>
@@ -880,7 +888,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"Aplikazioak exekutatzen ari dira atzeko planoan"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"Datu-konexioa desaktibatu nahi duzu?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"<xliff:g id="CARRIER">%s</xliff:g> erabilita ezingo dituzu erabili datuak edo Internet. Wi-Fi sare baten bidez soilik konektatu ahal izango zara Internetera."</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"<xliff:g id="CARRIER">%s</xliff:g> erabilita ezingo dituzu erabili datuak edo Internet. Wifi-sare baten bidez soilik konektatu ahal izango zara Internetera."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"Uneko operadorea"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Aplikazio bat baimen-eskaera oztopatzen ari denez, ezarpenek ezin dute egiaztatu erantzuna."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> aplikazioari <xliff:g id="APP_2">%2$s</xliff:g> aplikazioaren zatiak erakusteko baimena eman nahi diozu?"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Ireki <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren ezarpenen burbuilak"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren burbuilak erabiltzeko baimena eman nahi duzu?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Kudeatu"</string>
<string name="no_bubbles" msgid="337101288173078247">"Ukatu"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Onartu"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Galdetu geroago"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Eraman goialdera, eskuinetara"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Eraman behealdera, ezkerretara"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Eraman behealdera, eskuinetara"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 3bfa051..70fab45 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -26,7 +26,7 @@
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلانها"</string>
<string name="battery_low_title" msgid="9187898087363540349">"ممکن است باتری بهزودی تمام شود"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده است"</string>
- <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> باقی مانده، براساس میزان مصرف شما حدود <xliff:g id="TIME">%2$s</xliff:g> باقی مانده است"</string>
+ <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> باقی مانده، براساس اشتفاده شما حدود <xliff:g id="TIME">%2$s</xliff:g> باقی مانده است"</string>
<string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> باقی مانده، حدود <xliff:g id="TIME">%2$s</xliff:g> باقی مانده است"</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده است. بهینهسازی باتری روشن است."</string>
<string name="invalid_charger" msgid="2741987096648693172">"ازطریق USB شارژ نمیشود. از شارژر ارائهشده با دستگاه استفاده کنید."</string>
@@ -208,10 +208,10 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"اعلان ردشد."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"مجموعه اعلان."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"تنظیمات سریع."</string>
- <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"قفل صفحه."</string>
+ <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"صفحه قفل."</string>
<string name="accessibility_desc_settings" msgid="3417884241751434521">"تنظیمات"</string>
<string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"نمای کلی."</string>
- <string name="accessibility_desc_work_lock" msgid="4288774420752813383">"صفحه حالت قفل نمایه کاری"</string>
+ <string name="accessibility_desc_work_lock" msgid="4288774420752813383">"صفحه قفل کاری"</string>
<string name="accessibility_desc_close" msgid="7479755364962766729">"بستن"</string>
<string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wi-Fi خاموش شد."</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"ساعت <xliff:g id="TIME">%s</xliff:g> روشن میشود"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"تا <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"طرح زمینه تیره"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC غیرفعال است"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC فعال است"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"دوباره نشان داده نشود"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"پاک کردن همه موارد"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"مدیریت"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"اعلانهای ملایم"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"پاک کردن همه اعلانهای ملایم"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"اعلانها توسط «مزاحم نشوید» موقتاً متوقف شدند"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"اکنون شروع شود"</string>
<string name="empty_shade_text" msgid="708135716272867002">"اعلانی موجود نیست"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"صفحه نمایش پین شد"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"تا زمانی که پین را بردارید، در نما نگهداشته میشود. برای برداشتن پین، «برگشت» و «نمای کلی» را لمس کنید و نگهدارید."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"تا برداشتن پین، در نما نگهداشته میشود. برای برداشتن پین، «برگشت» و «صفحه اصلی» را لمس کنید و نگهدارید."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"تا برداشتن پین، در نما نگهداشته میشود. برای برداشتن پین، از پایین صفحه تند بهطرف بالا بکشید و نگهدارید."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"تا زمانی که پین را بردارید، در نما نگهداشته میشود. برای برداشتن پین، «نمای کلی» را لمس کنید و نگهدارید."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"تا برداشتن پین، در نما نگهداشته میشود. برای برداشتن پین، «صفحه اصلی» را لمس کنید و نگهدارید."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"برای برداشتن پین این صفحه، دکمههای «برگشت» و «نمای کلی» را لمس کنید و نگهدارید"</string>
@@ -615,7 +620,7 @@
<string name="tuner_full_importance_settings" msgid="3207312268609236827">"کنترلهای قدرتمند اعلان"</string>
<string name="tuner_full_importance_settings_on" msgid="7545060756610299966">"روشن"</string>
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"خاموش"</string>
- <string name="power_notification_controls_description" msgid="4372459941671353358">"با کنترلهای قدرتمند اعلان میتوانید سطح اهمیت اعلانهای هر برنامه را از ۰ تا ۵ تعیین کنید. \n\n"<b>"سطح ۵"</b>" \n- در صدر فهرست اعلانها نشان داده میشود \n- وقفه برای نمایش تمامصفحه مجاز است \n- همیشه اجمالی نشان داده میشود \n\n"<b>"سطح ۴"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- همیشه اجمالی نشان داده میشود \n\n"<b>"سطح ۳"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n\n"<b>"سطح ۲"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n- هیچوقت صدا و لرزش ایجاد نمیکند \n\n"<b>"سطح ۱"</b>" \n- نمایش تمام صفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n- هیچوقت صدا یا لرزش ایجاد نمیکند \n- در قفل صفحه و نوار وضعیت پنهان است \n- در پایین فهرست اعلانها نشان داده میشود \n\n"<b>"سطح ۰"</b>" \n- همه اعلانهای این برنامه مسدود است"</string>
+ <string name="power_notification_controls_description" msgid="4372459941671353358">"با کنترلهای قدرتمند اعلان میتوانید سطح اهمیت اعلانهای هر برنامه را از ۰ تا ۵ تعیین کنید. \n\n"<b>"سطح ۵"</b>" \n- در صدر فهرست اعلانها نشان داده میشود \n- وقفه برای نمایش تمامصفحه مجاز است \n- همیشه اجمالی نشان داده میشود \n\n"<b>"سطح ۴"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- همیشه اجمالی نشان داده میشود \n\n"<b>"سطح ۳"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n\n"<b>"سطح ۲"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n- هیچوقت صدا و لرزش ایجاد نمیکند \n\n"<b>"سطح ۱"</b>" \n- نمایش تمام صفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n- هیچوقت صدا یا لرزش ایجاد نمیکند \n- در صفحه قفل و نوار وضعیت پنهان است \n- در پایین فهرست اعلانها نشان داده میشود \n\n"<b>"سطح ۰"</b>" \n- همه اعلانهای این برنامه مسدود است"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"اعلانها"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"دیگر این اعلانها را نخواهید دید"</string>
<string name="notification_channel_minimized" msgid="1664411570378910931">"این اعلانها کوچک خواهد شد"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"نمایش اعلان از این برنامه ادامه یابد؟"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"آرام"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"دراولویت"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"همیشه بیصدا. در کشوی اعلانهای پایینکش نشان داده میشود."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"همیشه بیصدا. در کشوی اعلانهای پایینکش و نوار وضعیت نشان داده میشود."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"همیشه بیصدا. در کشوی اعلانهای پایینکش و در صفحه قفل نشان داده میشود."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"همیشه بیصدا. در کشوی اعلانهای پایینکش، نوار وضعیت در صفحه قفل نشان داده میشود."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"صدا پخش میشود و در کشوی اعلانهای پایینکش، نوار وضعیت و در صفحه قفل نشان داده میشود."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"با فقط نمایش اعلان در کشوی اعلانهای پایینکش، به شما کمک میکند تمرکزتان را ازدست ندهید همیشه بیصدا."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"اعلانهای با اولویت پایین را نشان میدهد. همیشه بیصدا."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"اعلانهای با اولویت پایین را نشان میدهد. همیشه بیصدا."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"اعلانهای با اولویت پایین را نشان میدهد. همیشه بیصدا."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"با صدا و نماد نوار وضعیت توجه شما را جلب میکند. در صفحه قفل نشان داده میشود."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"این اعلانها قابل اصلاح نیستند."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"نمیتوانید این گروه اعلانها را در اینجا پیکربندی کنید"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"اعلانهای دارای پراکسی"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"این برنامه از دوربین استفاده میکند."</string>
<string name="appops_microphone" msgid="741508267659494555">"این برنامه از میکروفون استفاده میکند."</string>
@@ -810,14 +818,14 @@
<string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"باز کردن تنظیمات سریع."</string>
<string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"بستن تنظیمات سریع."</string>
<string name="accessibility_quick_settings_alarm_set" msgid="1863000242431528676">"تنظیم زنگ ساعت."</string>
- <string name="accessibility_quick_settings_user" msgid="1567445362870421770">"با <xliff:g id="ID_1">%s</xliff:g> به سیستم وارد شدهاید"</string>
+ <string name="accessibility_quick_settings_user" msgid="1567445362870421770">"بهعنوان <xliff:g id="ID_1">%s</xliff:g> به سیستم وارد شدهاید"</string>
<string name="data_connection_no_internet" msgid="4503302451650972989">"عدم اتصال به اینترنت"</string>
<string name="accessibility_quick_settings_open_details" msgid="4230931801728005194">"باز کردن جزئیات."</string>
<string name="accessibility_quick_settings_not_available" msgid="4190068184294019846">"بهدلیل <xliff:g id="REASON">%s</xliff:g> دردسترس نیست"</string>
<string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"باز کردن تنظیمات <xliff:g id="ID_1">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ویرایش ترتیب تنظیمات."</string>
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"صفحه <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
- <string name="tuner_lock_screen" msgid="5755818559638850294">"قفل صفحه"</string>
+ <string name="tuner_lock_screen" msgid="5755818559638850294">"صفحه قفل"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"بزرگ کردن"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"کوچک کردن"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"بستن"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"باز کردن <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"تنظیم برای ابزارکهای اعلان <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"برای <xliff:g id="APP_NAME">%1$s</xliff:g>، ابزارکهای اعلان مجاز شوند؟"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"مدیریت"</string>
<string name="no_bubbles" msgid="337101288173078247">"رد کردن"</string>
<string name="yes_bubbles" msgid="668809525728633841">"اجازه دادن"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"بعداً پرسیده شود"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"انتقال به بالا سمت چپ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"انتقال به پایین سمت راست"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"انتقال به پایین سمت چپ"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index bdd5769..5e9ae30 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Käyttöön klo <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> saakka"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tumma teema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC on poistettu käytöstä"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC on käytössä"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Älä näytä uudelleen"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Poista kaikki"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Muuta asetuksia"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Varovaiset ilmoitukset"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Tyhjennä kaikki varovaiset ilmoitukset"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Älä häiritse ‑tila keskeytti ilmoitukset"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Aloita nyt"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Ei ilmoituksia"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Näyttö on kiinnitetty"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Edellinen ja Viimeisimmät."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Edellinen ja Aloitusnäyttö."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Pysyy näkyvissä, kunnes irrotat sen. Irrota pyyhkäisemällä ylös ja painamalla pitkään."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Viimeisimmät."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Aloitusnäyttö."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Irrota näyttö koskettamalla pitkään Takaisin- ja Viimeisimmät-painikkeita"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Jatketaanko ilmoitusten näyttämistä tästä sovelluksesta?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Varovainen"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Priorisoitu"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Aina äänetön. Näkyy vedettävällä ilmoitusalueella."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Aina äänetön. Näkyy vedettävällä ilmoitusalueella ja tilapalkissa."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Aina äänetön. Näkyy vedettävällä ilmoitusalueella ja lukitusnäytöllä."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Aina äänetön. Näkyy vedettävällä ilmoitusalueella, tilapalkissa ja lukitusnäytöllä."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Äänellinen ilmoitus näkyy vedettävällä ilmoitusalueella, tilapalkissa ja lukitusnäytöllä."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Keskittyminen on helpompaa, sillä ilmoitukset näkyvät vain alas vedettävällä alueella. Aina äänetön."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Näytetään priorisoitujen ilmoitusten alapuolella. Aina äänetön."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Näytetään priorisoitujen ilmoitusten alapuolella. Aina äänetön."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Näytetään priorisoitujen ilmoitusten alapuolella. Aina äänetön."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Kiinnittää huomion äänellä ja tilapalkin kuvakkeella. Näkyy lukitusnäytöllä."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Näitä ilmoituksia ei voi muokata"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Tätä ilmoitusryhmää ei voi määrittää tässä"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Välitetty ilmoitus"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Tämä sovellus käyttää kameraa."</string>
<string name="appops_microphone" msgid="741508267659494555">"Tämä sovellus käyttää mikrofonia."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Avaa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Kuplien asetukset: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Sallitaanko kuplat (<xliff:g id="APP_NAME">%1$s</xliff:g>)?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Ylläpidä"</string>
<string name="no_bubbles" msgid="337101288173078247">"Estä"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Salli"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Kysy myöhemmin"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Siirrä oikeaan yläreunaan"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Siirrä vasempaan alareunaan"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Siirrä oikeaan alareunaan"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 0837ddc..6d5777a 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Actif à <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Thème sombre"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC désactivée"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC activée"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ne plus afficher"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Tout effacer"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Gérer"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notifications discrètes"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Effacer toutes les notifications discrètes"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Les notifications sont suspendues par le mode Ne pas déranger"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Commencer"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Aucune notification"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"L\'écran est épinglé"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur « Retour » et « Aperçu »."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur les touches Retour et Accueil."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'épinglage. Pour annuler l\'épinglage, balayez l\'écran vers le haut et gardez le doigt dessus."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur « Aperçu »."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur la touche Accueil."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Pour annuler l\'épinglage de cet écran, maintenez le doigt sur les touches Retour et Aperçu."</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuer à afficher les notifications de cette application?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Discrètes"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Priorisées"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Toujours silencieux. S\'affiche dans le volet déroulant."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Toujours silencieux. S\'affiche dans le volet déroulant et dans la barre d\'état."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Toujours silencieux. S\'affiche dans le volet déroulant et sur l\'écran de verrouillage."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Toujours silencieux. S\'affiche dans le volet déroulant, dans la barre d\'état et sur l\'écran de verrouillage."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Émet un son et s\'affiche dans le volet déroulant, dans la barre d\'état et sur l\'écran de verrouillage."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Vous aide à vous concentrer en affichant seulement les notifications dans le volet déroulant. Toujours silencieux."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"S\'affiche sous les notifications prioritaires. Toujours silencieux."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"S\'affiche sous les notifications prioritaires. Toujours silencieux."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"S\'affiche sous les notifications prioritaires. Toujours silencieux."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Attire votre attention à l\'aide de sons et d\'une icône dans la barre d\'état. S\'affiche sur l\'écran de verrouillage."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Ces notifications ne peuvent pas être modifiées"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Ce groupe de notifications ne peut pas être configuré ici"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notification par mandataire"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Cette application utilise l\'appareil photo."</string>
<string name="appops_microphone" msgid="741508267659494555">"Cette application utilise le microphone."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Ouvrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Paramètres pour les bulles de l\'application <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Autoriser les bulles de l\'application <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Gérer"</string>
<string name="no_bubbles" msgid="337101288173078247">"Refuser"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Autoriser"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Me demander plus tard"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Déplacer dans coin sup. droit"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Déplacer dans coin inf. gauche"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Déplacer dans coin inf. droit"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 94a5222..5d1e863 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -67,7 +67,7 @@
<string name="usb_disable_contaminant_detection" msgid="2103905315747120033">"Activer le port USB"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"Capture d\'écran"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Capture"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"Enregistrement capture écran…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"Enregistrement de la capture d\'écran…"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"Capture d\'écran enregistrée"</string>
@@ -366,9 +366,11 @@
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Éclairage nocturne"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Activé la nuit"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Jusqu\'à l\'aube"</string>
- <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Activé à <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"À partir de <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Thème foncé"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"La technologie NFC est désactivée"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"La technologie NFC est activée"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ne plus afficher"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Tout effacer"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Gérer"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notifications discrètes"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Effacer toutes les notifications discrètes"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifications suspendues par le mode Ne pas déranger"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Commencer"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Aucune notification"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Écran épinglé"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Cet écran est épinglé jusqu\'à l\'annulation de l\'opération. Pour annuler l\'épinglage, appuyez de manière prolongée sur les boutons Retour et Aperçu."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Cet écran est épinglé jusqu\'à l\'annulation de l\'opération. Pour annuler l\'épinglage, appuyez de manière prolongée sur les boutons \"Retour\" et \"Accueil\"."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Cet écran est épinglé jusqu\'à l\'annulation de l\'opération. Pour annuler l\'épinglage, balayez l\'écran vers le haut et gardez le doigt dessus."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Cet écran est épinglé jusqu\'à l\'annulation de l\'opération. Pour annuler l\'épinglage, appuyez de manière prolongée sur le bouton Aperçu."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Cet écran est épinglé jusqu\'à l\'annulation de l\'opération. Pour annuler l\'épinglage, appuyez de manière prolongée sur le bouton \"Accueil\"."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Pour annuler l\'épinglage de l\'écran, appuyez de manière prolongée sur les boutons \"Retour\" et \"Aperçu\""</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuer d\'afficher les notifications de cette application ?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Discret"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritaire"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Toujours silencieux. S\'affiche dans le volet des notifications."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Toujours silencieux. S\'affiche dans le volet des notifications et dans la barre d\'état."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Toujours silencieux. S\'affiche dans le volet des notifications et sur l\'écran de verrouillage."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Toujours silencieux. S\'affiche dans le volet des notifications, dans la barre d\'état et sur l\'écran de verrouillage."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Émet un son et s\'affiche dans le volet des notifications, dans la barre d\'état et sur l\'écran de verrouillage."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Vous aide à vous concentrer en affichant les notifications seulement dans le volet déroulant. Toujours silencieux."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"S\'affiche sous les notifications prioritaires. Toujours silencieux."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"S\'affiche sous les notifications prioritaires. Toujours silencieux."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"S\'affiche sous les notifications prioritaires. Toujours silencieux."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Attire votre attention à l\'aide d\'un son et d\'une icône dans la barre d\'état. S\'affiche sur l\'écran de verrouillage."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Impossible de modifier ces notifications."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Vous ne pouvez pas configurer ce groupe de notifications ici"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notification de proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Cette application utilise la caméra."</string>
<string name="appops_microphone" msgid="741508267659494555">"Cette application utilise le micro."</string>
@@ -765,8 +773,8 @@
<string name="right_keycode" msgid="708447961000848163">"Code de touche droit"</string>
<string name="left_icon" msgid="3096287125959387541">"Icône gauche"</string>
<string name="right_icon" msgid="3952104823293824311">"Icône droite"</string>
- <string name="drag_to_add_tiles" msgid="230586591689084925">"Sélectionnez et faites glisser les tuiles pour les ajouter"</string>
- <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Sélectionnez et faites glisser les tuiles pour réorganiser"</string>
+ <string name="drag_to_add_tiles" msgid="230586591689084925">"Sélectionnez et faites glisser les icônes pour les ajouter"</string>
+ <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Sélectionnez et faites glisser les icônes pour réorganiser"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"Faites glisser les tuiles ici pour les supprimer."</string>
<string name="drag_to_remove_disabled" msgid="2390968976638993382">"Au minimum six tuiles sont nécessaires"</string>
<string name="qs_edit" msgid="2232596095725105230">"Modifier"</string>
@@ -880,7 +888,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"Applications en cours d\'exécution en arrière-plan"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Appuyer pour obtenir des informations sur l\'utilisation de la batterie et des données"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"Désactiver les données mobiles ?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"Vous n\'accéderez pas aux données mobiles ni à Internet via <xliff:g id="CARRIER">%s</xliff:g>. Internet ne sera disponible qu\'avec une connexion Wi-Fi."</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"Vous n\'aurez pas accès aux données mobiles ni à Internet via <xliff:g id="CARRIER">%s</xliff:g>. Vous ne pourrez accéder à Internet que par Wi-Fi."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"votre opérateur"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"L\'application Paramètres ne peut pas valider votre réponse, car une application masque la demande d\'autorisation."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"Autoriser <xliff:g id="APP_0">%1$s</xliff:g> à afficher des éléments de <xliff:g id="APP_2">%2$s</xliff:g> ?"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Ouvrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Paramètres des bulles de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Autoriser les bulles pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Gérer"</string>
<string name="no_bubbles" msgid="337101288173078247">"Refuser"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Autoriser"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Me demander plus tard"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Déplacer en haut à droite"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Déplacer en bas à gauche"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Déplacer en bas à droite"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 76a8dd3..f6f87e0 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -67,7 +67,7 @@
<string name="usb_disable_contaminant_detection" msgid="2103905315747120033">"Activar USB"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Ampliar ata ocupar todo"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Estirar ata ocupar todo"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Capt. pantalla"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"Gardando captura de pantalla…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"Gardando captura de pantalla…"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"Gardouse a captura de pantalla"</string>
@@ -82,7 +82,7 @@
<string name="screenrecord_mic_label" msgid="4522870600914810019">"Gravar voz en off"</string>
<string name="screenrecord_taps_label" msgid="1776467076607964790">"Mostrar toques"</string>
<string name="screenrecord_stop_label" msgid="2544887572381260038">"Deter"</string>
- <string name="screenrecord_pause_label" msgid="7162476078856786227">"Poñer en pausa"</string>
+ <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pór en pausa"</string>
<string name="screenrecord_resume_label" msgid="3605818317015993314">"Retomar"</string>
<string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancelar"</string>
<string name="screenrecord_share_label" msgid="4197867360204019389">"Compartir"</string>
@@ -366,9 +366,11 @@
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz nocturna"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Activación ao solpor"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Ata o amencer"</string>
- <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Activación (<xliff:g id="TIME">%s</xliff:g>)"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Desde: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Ata: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema escuro"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"A opción NFC está desactivada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"A opción NFC está activada"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Non mostrar outra vez"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Eliminar todas"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Xestionar"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notificacións discretas"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Borra todas as notificacións discretas"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"O modo Non molestar puxo en pausa as notificacións"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Iniciar agora"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Non hai notificacións"</string>
@@ -525,16 +529,17 @@
<string name="volume_odi_captions_hint_disable" msgid="8980842810619956593">"desactiva"</string>
<string name="accessibility_output_chooser" msgid="8185317493017988680">"Cambia ao dispositivo de saída"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"A pantalla está fixada"</string>
- <string name="screen_pinning_description" msgid="8909878447196419623">"A pantalla manterase visible ata que a soltes. Para facelo, mantén premido Atrás e Visión xeral."</string>
- <string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"A pantalla manterase visible ata que a soltes. Para facelo, mantén premido Atrás e Inicio."</string>
- <string name="screen_pinning_description_accessible" msgid="426190689254018656">"A pantalla manterase visible ata que a soltes. Para facelo, mantén premido Visión xeral."</string>
- <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"A pantalla manterase visible ata que a soltes. Para facelo, mantén premido Inicio."</string>
- <string name="screen_pinning_toast" msgid="2266705122951934150">"Para soltar a pantalla, mantén premidos os botóns Volver e Visión xeral"</string>
- <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"Para soltar a pantalla, mantén premidos os botóns Atrás e Inicio"</string>
+ <string name="screen_pinning_description" msgid="8909878447196419623">"A pantalla manterase visible ata que deixes de fixala. Para facelo, mantén premido Atrás e Visión xeral."</string>
+ <string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"A pantalla manterase visible ata que deixes de fixala. Para facelo, mantén premido Atrás e Inicio."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"A pantalla manterase visible ata que deixes de fixala. Para facelo, pasa o dedo cara arriba e manteno premido."</string>
+ <string name="screen_pinning_description_accessible" msgid="426190689254018656">"A pantalla manterase visible ata que deixes de fixala. Para facelo, mantén premido Visión xeral."</string>
+ <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"A pantalla manterase visible ata que deixes de fixala. Para facelo, mantén premido Inicio."</string>
+ <string name="screen_pinning_toast" msgid="2266705122951934150">"Para deixar de fixar a pantalla, mantén premidos os botóns Volver e Visión xeral"</string>
+ <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"Para deixar de fixar a pantalla, mantén premidos os botóns Atrás e Inicio"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"De acordo"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Non, grazas"</string>
<string name="screen_pinning_start" msgid="1022122128489278317">"Fixouse a pantalla"</string>
- <string name="screen_pinning_exit" msgid="5187339744262325372">"Soltouse a pantalla"</string>
+ <string name="screen_pinning_exit" msgid="5187339744262325372">"Deixouse de fixar a pantalla"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Queres ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Volverá aparecer a próxima vez que se active na configuración."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Queres seguir mostrando as notificacións desta aplicación?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Discretas"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritarias"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Sempre en silencio. Móstrase na lista despregable."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Sempre en silencio. Móstrase na lista despregable e na barra de estado."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Sempre en silencio. Móstrase na lista despregable e na pantalla de bloqueo."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Sempre en silencio. Móstrase na lista despregable, na barra de estado e na pantalla de bloqueo."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Reproduce un son e móstrase na lista despregable, na barra de estado e na pantalla de bloqueo."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Permíteche centrarte con notificacións só no panel despregable. Sempre en silencio."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Mostra as notificacións con prioridade baixa. Sempre en silencio."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Mostra as notificacións con prioridade baixa. Sempre en silencio."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Mostra as notificacións con prioridade baixa. Sempre en silencio."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Chama a túa atención cun son e cunha icona na barra de estado Móstrase na pantalla de bloqueo."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Estas notificacións non se poden modificar."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Aquí non se pode configurar este grupo de notificacións"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notificación mediante proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Esta aplicación está utilizando a cámara."</string>
<string name="appops_microphone" msgid="741508267659494555">"Esta aplicación está utilizando o micrófono."</string>
@@ -859,7 +867,7 @@
<string name="notification_channel_general" msgid="4525309436693914482">"Mensaxes xerais"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamento"</string>
<string name="notification_channel_hints" msgid="7323870212489152689">"Consellos"</string>
- <string name="instant_apps" msgid="6647570248119804907">"Aplicacións instantáneas"</string>
+ <string name="instant_apps" msgid="6647570248119804907">"Aplicacións Instantáneas"</string>
<string name="instant_apps_title" msgid="8738419517367449783">"Estase executando <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="instant_apps_message" msgid="1183313016396018086">"Abriuse a aplicación sen ter que instalala."</string>
<string name="instant_apps_message_with_help" msgid="6179830437630729747">"Abriuse a aplicación sen ter que instalala. Tocar para obter máis información."</string>
@@ -909,8 +917,9 @@
<string name="music_controls_no_title" msgid="5236895307087002011">"Sen título"</string>
<string name="restart_button_description" msgid="2035077840254950187">"Toca o botón para reiniciar esta aplicación e abrila en pantalla completa."</string>
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Abre a aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="bubbles_settings_button_description" msgid="2970630476657287189">"Configuración dos globos de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="bubbles_prompt" msgid="8807968030159469710">"Queres permitir que se mostren os globos de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="bubbles_settings_button_description" msgid="2970630476657287189">"Configuración das burbullas de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_prompt" msgid="8807968030159469710">"Queres permitir que se mostren as burbullas de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Xestionar"</string>
<string name="no_bubbles" msgid="337101288173078247">"Denegar"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Permitir"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Preguntarme máis tarde"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Mover á parte superior dereita"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Mover á parte infer. esquerda"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Mover á parte inferior dereita"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index a832a7b..e5a7424 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> વાગ્યે"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> સુધી"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"ઘેરી થીમ"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC અક્ષમ કરેલ છે"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC સક્ષમ કરેલ છે"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"ફરીથી બતાવશો નહીં"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"બધુ સાફ કરો"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"મેનેજ કરો"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"સામાન્ય નોટિફિકેશન"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"બધા સામાન્ય નોટિફિકેશન સાફ કરો"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"ખલેલ પાડશો નહીં દ્વારા થોભાવેલ નોટિફિકેશન"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"હવે પ્રારંભ કરો"</string>
<string name="empty_shade_text" msgid="708135716272867002">"કોઈ સૂચનાઓ નથી"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"સ્ક્રીન પિન કરેલ છે"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને દૃશ્યક્ષમ રાખે છે. અનપિન કરવા માટે પાછળ અને ઝલકને સ્પર્શ કરી રાખો."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને દૃશ્યક્ષમ રાખે છે. અનપિન કરવા માટે પાછળ અને હોમને સ્પર્શ કરી રાખો."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"તમે જ્યાં સુધી અનપિન નહીં કરો ત્યાં સુધી આ તેને દૃશ્યક્ષમ રાખે છે. ઉપરની તરફ સ્વાઇપ કરો અને અનપિન કરવા માટે દબાવી રાખો."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને દૃશ્યક્ષમ રાખે છે. અનપિન કરવા માટે ઝલકને સ્પર્શ કરી રાખો."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને દૃશ્યક્ષમ રાખે છે. અનપિન કરવા માટે હોમને સ્પર્શ કરી રાખો."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"આ સ્ક્રીનને અનપિન કરવા માટે, પાછળ અને ઝલક બટનને સ્પર્શ કરી રાખો"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"આ ઍપમાંથી નોટિફિકેશન બતાવવાનું ચાલુ રાખીએ?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"સામાન્ય નોટિફિકેશન"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"મહત્ત્વના નોટિફિકેશન"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"હંમેશાં સાઇલન્ટ. નીચે દેખાતા શેડમાં બતાવવામાં આવશે."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"હંમેશાં સાઇલન્ટ. નીચે દેખાતા શેડમાં અને સ્ટેટસ બારમાં બતાવવામાં આવશે."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"હંમેશાં સાઇલન્ટ. નીચે દેખાતા શેડમાં અને લૉક સ્ક્રીનમાં બતાવવામાં આવશે."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"હંમેશાં સાઇલન્ટ. નીચે દેખાતા શેડ, સ્ટેટસ બાર અને લૉક સ્ક્રીનમાં બતાવવામાં આવશે."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"અવાજ કરશે અને નીચે દેખાતા શેડ, સ્ટેટસ બાર અને લૉક સ્ક્રીનમાં બતાવવામાં આવશે."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"નીચે દેખાતા શેડમાં માત્ર નોટિફિકેશન પર ફોકસ કરવામાં તમને સહાય કરે છે. હંમેશાં સાઇલન્ટ."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"પ્રાધાન્યતાવાળા નોટિફિકેશન નીચે બતાવે છે. હંમેશાં સાઇલન્ટ."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"પ્રાધાન્યતાવાળા નોટિફિકેશન નીચે બતાવે છે. હંમેશાં સાઇલન્ટ."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"પ્રાધાન્યતાવાળા નોટિફિકેશન નીચે બતાવે છે. હંમેશાં સાઇલન્ટ."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"સાઉન્ડ અને સ્ટેટસ બાર આઇકન તમારું ધ્યાન દોરે છે. લૉક સ્ક્રીન પર બતાવે છે."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"આ નોટિફિકેશનમાં કોઈ ફેરફાર થઈ શકશે નહીં."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"નોટિફિકેશનના આ ગ્રૂપની ગોઠવણી અહીં કરી શકાશે નહીં"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"પ્રૉક્સી નોટિફિકેશન"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"આ ઍપ કૅમેરાનો ઉપયોગ કરી રહી છે."</string>
<string name="appops_microphone" msgid="741508267659494555">"આ ઍપ માઇક્રોફોનનો ઉપયોગ કરી રહી છે."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> ખોલો"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> બબલ માટેનાં સેટિંગ"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> પરના બબલને મંજૂરી આપીએ?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"મેનેજ કરો"</string>
<string name="no_bubbles" msgid="337101288173078247">"નકારો"</string>
<string name="yes_bubbles" msgid="668809525728633841">"મંજૂરી આપો"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"મને થોડા સમય પછી પૂછશો"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"ઉપર જમણે ખસેડો"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"નીચે ડાબે ખસેડો"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"નીચે જમણે ખસેડો"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 74e9cfe..17c2681 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -252,10 +252,10 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"मोबाइल हॉटस्पॉट को बंद किया गया."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"मोबाइल हॉटस्पॉट को चालू किया गया."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"स्क्रीन कास्ट करना रुक गया."</string>
- <string name="accessibility_quick_settings_work_mode_off" msgid="7045417396436552890">"कार्य मोड बंद है."</string>
- <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"कार्य मोड चालू है."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"कार्य मोड बंद कर दिया गया."</string>
- <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"कार्य मोड चालू किया गया."</string>
+ <string name="accessibility_quick_settings_work_mode_off" msgid="7045417396436552890">"वर्क मोड बंद है."</string>
+ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"वर्क मोड चालू है."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"वर्क मोड बंद कर दिया गया."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"वर्क मोड चालू किया गया."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"डेटा बचाने की सेटिंग बंद कर दी गई है."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"डेटा बचाने की सेटिंग चालू कर दी गई है."</string>
<string name="accessibility_quick_settings_sensor_privacy_changed_off" msgid="5152819588955163090">"सेंसर निजता को बंद कर दिया गया है."</string>
@@ -362,13 +362,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> उपयोग किया गया"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> सीमा"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी"</string>
- <string name="quick_settings_work_mode_label" msgid="7608026833638817218">"कार्य प्रोफ़ाइल"</string>
+ <string name="quick_settings_work_mode_label" msgid="7608026833638817218">"वर्क प्रोफ़ाइल"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"नाइट लाइट"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"शाम को चालू की जाएगी"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"सुबह तक चालू रहेगी"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> पर चालू की जाएगी"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> तक"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"गहरे रंग वाली थीम"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"एनएफ़सी"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC बंद है"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC चालू है"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"फिर से न दिखाएं"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"सभी को हटाएं"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"प्रबंधित करें"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"बिना आवाज़ वाली सूचनाएं"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"बिना आवाज़ वाली सभी सूचनाएं हटाएं"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\'परेशान न करें\' सुविधा के ज़रिए कुछ समय के लिए सूचनाएं दिखाना रोक दिया गया है"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"अब शुरू करें"</string>
<string name="empty_shade_text" msgid="708135716272867002">"कोई सूचना नहीं मिली"</string>
@@ -462,11 +466,11 @@
<string name="quick_settings_disclosure_named_management" msgid="1059403025094542908">"डिवाइस का प्रबंधन <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> करता है"</string>
<string name="quick_settings_disclosure_management_vpns" msgid="3698767349925266482">"डिवाइस का प्रबंधन आपका संगठन करता है और वह VPNs से कनेक्ट है"</string>
<string name="quick_settings_disclosure_named_management_vpns" msgid="7777821385318891527">"डिवाइस का प्रबंधन <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> करता है और वह VPNs से कनेक्ट है"</string>
- <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="5125463987558278215">"आपका संगठन आपकी कार्य प्रोफ़ाइल में नेटवर्क ट्रैफ़िक की निगरानी कर सकता है"</string>
- <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8973606847896650284">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> आपकी कार्य प्रोफ़ाइल में नेटवर्क ट्रैफ़िक की निगरानी कर सकता है"</string>
+ <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="5125463987558278215">"आपका संगठन आपकी वर्क प्रोफ़ाइल में नेटवर्क ट्रैफ़िक की निगरानी कर सकता है"</string>
+ <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8973606847896650284">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> आपकी वर्क प्रोफ़ाइल में नेटवर्क ट्रैफ़िक की निगरानी कर सकता है"</string>
<string name="quick_settings_disclosure_monitoring" msgid="679658227269205728">"नेटवर्क की निगरानी की जा सकती है"</string>
<string name="quick_settings_disclosure_vpns" msgid="8170318392053156330">"डिवाइस VPNs से कनेक्ट है"</string>
- <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="3494535754792751741">"कार्य प्रोफ़ाइल <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट है"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="3494535754792751741">"वर्क प्रोफ़ाइल <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट है"</string>
<string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="4467456202486569906">"व्यक्तिगत प्रोफ़ाइल <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट है"</string>
<string name="quick_settings_disclosure_named_vpn" msgid="6943724064780847080">"डिवाइस <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट है"</string>
<string name="monitoring_title_device_owned" msgid="1652495295941959815">"डिवाइस प्रबंधन"</string>
@@ -481,12 +485,12 @@
<string name="monitoring_description_named_management" msgid="5281789135578986303">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> आपके डिवाइस का प्रबंधन करता है.\n\nआपका एडमिन सेटिंग, कॉर्पोरेट पहुंच, ऐप्लिकेशन, आपके डिवाइस से जुड़े डेटा और आपके डिवाइस की जगह की जानकारी की निगरानी कर सकता है और उन्हें प्रबंधित कर सकता है.\n\n और जानकारी के लिए, अपने एडमिन से संपर्क करें."</string>
<string name="monitoring_description_management" msgid="4573721970278370790">"आपका संगठन आपके डिवाइस का प्रबंधन करता है.\n\nआपका एडमिन सेटिंग, कॉर्पोरेट पहुंच, ऐप्लिकेशन, आपके डिवाइस से जुड़े डेटा और आपके डिवाइस की जगह की जानकारी की निगरानी कर सकता है और उन्हें प्रबंधित कर सकता है.\n\nऔर जानकारी के लिए, अपने एडमिन से संपर्क करें."</string>
<string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"आपके संगठन ने इस डिवाइस पर एक प्रमाणपत्र अनुमति इंस्टॉल की है. आपके सुरक्षित नेटवर्क पर ट्रेफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string>
- <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"आपके संगठन ने आपकी कार्य प्रोफ़ाइल में एक प्रमाणपत्र अनुमति इंस्टॉल की है. आपके सुरक्षित नेटवर्क ट्रैफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string>
+ <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"आपके संगठन ने आपकी वर्क प्रोफ़ाइल में एक प्रमाणपत्र अनुमति इंस्टॉल की है. आपके सुरक्षित नेटवर्क ट्रैफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string>
<string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"इस डिवाइस पर एक प्रमाणपत्र अनुमति इंस्टॉल की है. आपके सुरक्षित नेटवर्क ट्रैफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string>
<string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"आपके व्यवस्थापक ने नेटवर्क लॉगिंग चालू किया है, जो आपके डिवाइस पर ट्रैफ़िक की निगरानी करता है."</string>
<string name="monitoring_description_named_vpn" msgid="7403457334088909254">"आप <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकते हैं."</string>
<string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"आप <xliff:g id="VPN_APP_0">%1$s</xliff:g> और <xliff:g id="VPN_APP_1">%2$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकते हैं."</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"आपकी कार्य प्रोफ़ाइल <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"आपकी वर्क प्रोफ़ाइल <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"आपकी व्यक्तिगत प्रोफ़ाइल <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
<string name="monitoring_description_do_header_generic" msgid="96588491028288691">"<xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> आपका डिवाइस प्रबंधित करता है."</string>
<string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> आपका डिवाइस प्रबंधित करने के लिए <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> का उपयोग करता है."</string>
@@ -506,11 +510,11 @@
<string name="monitoring_description_app_personal" msgid="484599052118316268">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्स और वेबसाइटों सहित आपकी व्यक्तिगत नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइट सहित आपकी व्यक्तिगत नेटवर्क गतिविधि को मॉनिटर कर सकता है."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"आपकी वर्क प्रोफ़ाइल का प्रबंधन <xliff:g id="ORGANIZATION">%1$s</xliff:g> करता है. प्रोफ़ाइल <xliff:g id="APPLICATION">%2$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nऔर जानकारी के लिए, अपने एडमिन से संपर्क करें."</string>
- <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"आपकी कार्य प्रोफ़ाइल का प्रबंधन <xliff:g id="ORGANIZATION">%1$s</xliff:g> करता है. प्रोफ़ाइल <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nआप <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> से भी कनेक्ट हैं, जो आपकी व्यक्तिगत नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
+ <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"आपकी वर्क प्रोफ़ाइल का प्रबंधन <xliff:g id="ORGANIZATION">%1$s</xliff:g> करता है. प्रोफ़ाइल <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nआप <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> से भी कनेक्ट हैं, जो आपकी व्यक्तिगत नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
<string name="keyguard_indication_trust_unlocked" msgid="2712865815371519117">"TrustAgent की वजह से अनलॉक रखा गया है"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"जब तक कि आप मैन्युअल रूप से अनलॉक नहीं करते तब तक डिवाइस लॉक रहेगा"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"सूचनाएं ज़्यादा तेज़ी से पाएं"</string>
- <string name="hidden_notifications_text" msgid="2326409389088668981">"आपके द्वारा उन्हें अनलॉक किए जाने से पहले देखें"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">" उन्हें अनलॉक किए जाने से पहले देखें"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"रहने दें"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"सेट करें"</string>
<string name="zen_mode_and_condition" msgid="4462471036429759903">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"स्क्रीन पिन कर दी गई है"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"इससे वह तब तक दिखता रहता है जब तक कि आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, \'वापस जाएं\' और \'खास जानकारी\' को दबाकर रखें."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"इससे वह तब तक दिखाई देती है जब तक आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, होम और वापस जाएं वाले बटन को दबाकर रखें."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"इससे ऐप्लिकेशन की स्क्रीन तब तक दिखाई देती है जब तक आप उसे अनपिन नहीं करते. अनपिन करने के लिए ऊपर स्वाइप करें और स्क्रीन दबाकर रखें."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"इससे वह तब तक दिखता रहता है जब तक कि आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, \'खास जानकारी\' को दबाकर रखें."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"इससे वह तब तक दिखाई देती है जब तक आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, होम बटन को दबाकर रखें."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"इस स्क्रीन को अनपिन करने के लिए, खास जानकारी और वापस जाएं वाले बटन को दबाकर रखें"</string>
@@ -581,7 +586,7 @@
<string name="show_demo_mode" msgid="2018336697782464029">"डेमो मोड दिखाएं"</string>
<string name="status_bar_ethernet" msgid="5044290963549500128">"ईथरनेट"</string>
<string name="status_bar_alarm" msgid="8536256753575881818">"अलार्म"</string>
- <string name="status_bar_work" msgid="6022553324802866373">"कार्य प्रोफ़ाइल"</string>
+ <string name="status_bar_work" msgid="6022553324802866373">"वर्क प्रोफ़ाइल"</string>
<string name="status_bar_airplane" msgid="7057575501472249002">"हवाई जहाज़ मोड"</string>
<string name="add_tile" msgid="2995389510240786221">"टाइल जोड़ें"</string>
<string name="broadcast_tile" msgid="3894036511763289383">"टाइल प्रसारित करें"</string>
@@ -591,7 +596,7 @@
<string name="alarm_template_far" msgid="4242179982586714810">"<xliff:g id="WHEN">%1$s</xliff:g> पर"</string>
<string name="accessibility_quick_settings_detail" msgid="2579369091672902101">"तेज़ सेटिंग, <xliff:g id="TITLE">%s</xliff:g>."</string>
<string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"हॉटस्पॉट"</string>
- <string name="accessibility_managed_profile" msgid="6613641363112584120">"कार्य प्रोफ़ाइल"</string>
+ <string name="accessibility_managed_profile" msgid="6613641363112584120">"वर्क प्रोफ़ाइल"</string>
<string name="tuner_warning_title" msgid="7094689930793031682">"कुछ के लिए मज़ेदार लेकिन सबके लिए नहीं"</string>
<string name="tuner_warning" msgid="8730648121973575701">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर, आपको Android यूज़र इंटरफ़ेस में सुधार लाने और उसे अपनी पसंद के हिसाब से बदलने के कुछ और तरीके देता है. प्रयोग के तौर पर इस्तेमाल हो रहीं ये सुविधाएं आगे चल कर रिलीज़ की जा सकती हैं, रोकी जा सकती हैं या दिखाई देना बंद हो सकती हैं. सावधानी से आगे बढ़ें."</string>
<string name="tuner_persistent_warning" msgid="8597333795565621795">"ये प्रयोगात्मक सुविधाएं आगामी रिलीज़ में बदल सकती हैं, रुक सकती हैं या दिखाई देना बंद हो सकती हैं. सावधानी से आगे बढ़ें."</string>
@@ -611,7 +616,7 @@
<string name="show_silently" msgid="6841966539811264192">"सूचना बिना आवाज़ के दिखाएं"</string>
<string name="block" msgid="2734508760962682611">"सभी सूचनाएं रोकें"</string>
<string name="do_not_silence" msgid="6878060322594892441">"मौन ना करें"</string>
- <string name="do_not_silence_block" msgid="4070647971382232311">"मौन या अवरुद्ध ना करें"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"मौन या ब्लॉक ना करें"</string>
<string name="tuner_full_importance_settings" msgid="3207312268609236827">"पावर सूचना नियंत्रण"</string>
<string name="tuner_full_importance_settings_on" msgid="7545060756610299966">"चालू"</string>
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"बंद"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"इस ऐप्लिकेशन से जुड़ी सूचनाएं दिखाना जारी रखें?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"बिना आवाज़ के"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"ज़रूरी"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"हमेशा आवाज़ और वाइब्रेशन के बिना दिखाएं. नीचे खींचने वाली सूची में दिखाएं."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"हमेशा आवाज़ और वाइब्रेशन के बिना दिखाएं. नीचे खींचने वाली सूची और स्टेटस बार पर दिखाएं."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"हमेशा आवाज़ और वाइब्रेशन के बिना दिखाएं. नीचे खींचने वाली सूची और लॉक स्क्रीन पर दिखाएं."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"हमेशा आवाज़ और वाइब्रेशन के बिना दिखाएं. नीचे खींचने वाली सूची, स्टेटस बार और लॉक स्क्रीन पर दिखाएं."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"सूचना आने पर आवाज़ हाे और नीचे खींचने वाली सूची, स्टेटस बार और लॉक स्क्रीन पर भी दिखाई दे."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"सिर्फ़ नीचे खिंचने वाली सूची में सूचनाएं दिखती हैं ताकि आप उन पर पूरा ध्यान दे सकें. दिखते समय आवाज़ और वाइब्रेशन हमेशा बंद रहते हैं."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"कम ज़रूरी सूचनाएं दिखती हैं. दिखते समय आवाज़ और वाइब्रेशन हमेशा बंद रहते हैं."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"कम ज़रूरी सूचनाएं दिखती हैं. दिखते समय आवाज़ और वाइब्रेशन हमेशा बंद रहते हैं."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"कम ज़रूरी सूचनाएं दिखती हैं. दिखते समय आवाज़ और वाइब्रेशन हमेशा बंद रहते हैं."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"आवाज़ और स्टेटस बार के आइकॉन की मदद से सूचनाओं पर आपका ध्यान खिंचता है. लॉक स्क्रीन पर दिखाई देता है."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"ये सूचनाएं नहीं बदली जा सकती हैं."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"सूचनाओं के इस समूह को यहां कॉन्फ़िगर नहीं किया जा सकता"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"प्रॉक्सी सूचना"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"यह ऐप्लिकेशन कैमरे का इस्तेमाल कर रहा है."</string>
<string name="appops_microphone" msgid="741508267659494555">"यह ऐप्लिकेशन माइक्रोफ़ोन का इस्तेमाल कर रहा है."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> खोलें"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> बबल की सेटिंग"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> से बबल की अनुमति दें?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"प्रबंधित करें"</string>
<string name="no_bubbles" msgid="337101288173078247">"अनुमति न दें"</string>
<string name="yes_bubbles" msgid="668809525728633841">"अनुमति दें"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"मुझसे बाद में पूछें"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"सबसे ऊपर दाईं ओर ले जाएं"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"बाईं ओर सबसे नीचे ले जाएं"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"सबसे नीचे दाईं ओर ले जाएं"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 6a1b1c2..cea0529 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -307,7 +307,7 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="4930931771490695395">"Slušni aparati"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="4551281899312150640">"Uključivanje…"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Svjetlina"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatsko izmjenjivanje"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatsko zakretanje"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automatsko zakretanje zaslona"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"Način: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Izmjenjivanje je zaključano"</string>
@@ -371,6 +371,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tamna tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je onemogućen"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je omogućen"</string>
@@ -451,6 +453,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ne prikazuj ponovo"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Izbriši sve"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Upravljajte"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Neupadljive obavijesti"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Izbrišite sve neupadljive obavijesti"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Značajka Ne uznemiravaj pauzirala je Obavijesti"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Započni sad"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Nema obavijesti"</string>
@@ -530,6 +534,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Zaslon je prikvačen"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite i zadržite Natrag i Pregled da biste ga otkvačili."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite gumbe Natrag i Početna i zadržite pritisak da biste ga otkvačili."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Prijeđite prstom prema gore i zadržite da biste ga otkvačili."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite i zadržite Pregled da biste ga otkvačili."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite gumb Početna i zadržite pritisak da biste ga otkvačili."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Da biste otkvačili ovaj zaslon, dodirnite gumbe Natrag i Pregled i zadržite pritisak"</string>
@@ -641,14 +646,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Želite li da se obavijesti te aplikacije nastave prikazivati?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Neupadljivo"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritetno"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Uvijek bešumno. Prikazuje se na zaslonu obavijesti."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Uvijek bešumno. Prikazuje se na zaslonu obavijesti i traci statusa."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Uvijek bešumno. Prikazuje se na zaslonu obavijesti i zaključanom zaslonu."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Uvijek bešumno. Prikazuje se na zaslonu obavijesti, traci statusa i zaključanom zaslonu."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Prikazuje se na zaslonu obavijesti, traci statusa i zaključanom zaslonu uz zvučni signal."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Pomaže vam da se usredotočite prikazujući obavijesti samo na zaslonu obavijesti. Uvijek bešumno."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Prikazuje se ispod prioritetnih obavijesti. Uvijek bešumno."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Prikazuje se ispod prioritetnih obavijesti. Uvijek bešumno."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Prikazuje se ispod prioritetnih obavijesti. Uvijek bešumno."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Privlači vašu pažnju zvučnim signalom i ikonom na traci statusa. Prikazuje se na zaključanom zaslonu."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Te se obavijesti ne mogu izmijeniti."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Ta se grupa obavijesti ne može konfigurirati ovdje"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Obavijest poslana putem proxyja"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Ova aplikacija upotrebljava kameru."</string>
<string name="appops_microphone" msgid="741508267659494555">"Ova aplikacija upotrebljava mikrofon."</string>
@@ -916,6 +924,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Otvorite aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Postavke za oblačiće za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Želite li dopustiti oblačiće iz aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Upravljanje"</string>
<string name="no_bubbles" msgid="337101288173078247">"Odbij"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Dopusti"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Pitaj me kasnije"</string>
@@ -926,4 +935,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Premjesti u gornji desni kut"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Premjesti u donji lijevi kut"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Premjestite u donji desni kut"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 11e49d1..cc0c07d 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Bekapcsolás: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Eddig: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Sötét téma"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Az NFC ki van kapcsolva"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Az NFC be van kapcsolva"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ne jelenjen meg többé"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Az összes törlése"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Kezelés"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Diszkrét értesítések"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Az összes diszkrét értesítés törlése"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Ne zavarjanak funkcióval szüneteltetett értesítések"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Indítás most"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Nincs értesítés"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"A képernyő rögzítve van"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva a Vissza és az Áttekintés lehetőséget."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva a Vissza és a Kezdőképernyő elemet."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz csúsztasson fel, és tartsa ujját a képernyőn."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva az Áttekintés lehetőséget."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva a Kezdőképernyő elemet."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"A képernyő rögzítésének feloldásához tartsa lenyomva a Vissza és az Áttekintés gombot"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Továbbra is megjelenjenek az alkalmazás értesítései?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Diszkrét"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritásos"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Mindig némítva. A lehúzható értesítési felületen jelenik meg."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Mindig némítva. A lehúzható értesítési felületen és az állapotsoron jelenik meg."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Mindig némítva. A lehúzható értesítési felületen és a lezárási képernyőn jelenik meg."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Mindig némítva. A lehúzható értesítési felületen, az állapotsoron és a lezárási képernyőn jelenik meg."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Hangot ad, és megjelenik a lehúzható értesítési felületen, az állapotsoron és a lezárási képernyőn."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Segítségével a fontos dolgokra koncentrálhat, az értesítések csak a lehúzható értesítési felületen jelennek meg. Mindig némítva van."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Az elsőbbségi értesítések alatt jelenik meg. Mindig némítva van."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Az elsőbbségi értesítések alatt jelenik meg. Mindig némítva van."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Az elsőbbségi értesítések alatt jelenik meg. Mindig némítva van."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Figyelemfelkeltő a hangjelzésnek és az állapotsávon megjelenő ikonnak köszönhetően. Megjelenik a lezárási képernyőn."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Ezeket az értesítéseket nem lehet módosítani."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Az értesítések jelen csoportját itt nem lehet beállítani"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Továbbított értesítés"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Ez az alkalmazás használja a kamerát."</string>
<string name="appops_microphone" msgid="741508267659494555">"Ez az alkalmazás használja a mikrofont."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> megnyitása"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g>-buborékok beállításai"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Engedélyezi a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazásból származó buborékokat?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Kezelés"</string>
<string name="no_bubbles" msgid="337101288173078247">"Tiltás"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Engedélyezés"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Kérdezzen rá később"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Áthelyezés fel és jobbra"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Áthelyezés le és balra"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Áthelyezés le és jobbra"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 949a5eb..c6faea5 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -292,7 +292,7 @@
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_header_onboarding_text" msgid="8030309023792936283">"Լրացուցիչ կարգավորումները բացելու համար հպեք և պահեք պատկերակները"</string>
<string name="quick_settings_dnd_label" msgid="7112342227663678739">"Չանհանգստացնել"</string>
- <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Միայն կարևոր ծանուցումների դեպքում"</string>
+ <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Միայն կարևոր ծանուցումներ"</string>
<string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Միայն զարթուցիչ"</string>
<string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"Կատարյալ լռություն"</string>
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Կմիացվի ժամը <xliff:g id="TIME">%s</xliff:g>-ին"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Մինչև <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Մուգ թեմա"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC-ն անջատված է"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC-ն միացված է"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Այլևս ցույց չտալ"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Մաքրել բոլորը"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Կառավարել"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Չհոգնեցնող ծանուցումներ"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Ջնջել բոլոր չհոգնեցնող ծանուցումները"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Ծանուցումները չեն ցուցադրվի «Չանհանգստացնել» ռեժիմում"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Սկսել հիմա"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Ծանուցումներ չկան"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Էկրանն ամրացված է"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Էկրանը կմնա տեսադաշտում, մինչև այն ապամրացնեք: Ապամրացնելու համար հպեք և պահեք Հետ և Համատեսք կոճակները:"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Էկրանը կցուցադրվի այնքան ժամանակ, մինչև որ չապամրացնեք այն: Ապամրացնելու համար հպեք և պահեք Հետ և գլխավոր էկրանի կոճակները:"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Էկրանը կցուցադրվի այնքան ժամանակ, մինչև որ չապամրացնեք այն: Ապամրացնելու համար մատը սահեցրեք վեր և պահեք։"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Էկրանը կմնա տեսադաշտում, մինչև այն ապամրացնեք: Ապամրացնելու համար հպեք և պահեք Համատեսք կոճակը:"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Էկրանը կցուցադրվի այնքան ժամանակ, մինչև որ չապամրացնեք այն: Ապամրացնելու համար հպեք և պահեք գլխավոր էկրանի կոճակը:"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Էկրանն ապամրացնելու համար հպեք և պահեք Հետ և Համատեսք կոճակները"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Ցուցադրե՞լ ծանուցումներ այս հավելվածից։"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Անձայն"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Առաջնահերթ"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Միշտ անձայն: Ցուցադրվում է իջնող վահանակի վրա:"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Միշտ անձայն: Ցուցադրվում է իջնող վահանակի վրա և կարգավիճակի գոտում:"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Միշտ անձայն: Ցուցադրվում է իջնող վահանակի վրա և կողպէկրանին:"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Միշտ անձայն: Ցուցադրվում է իջնող վահանակի վրա, կարգավիճակի գոտում և կողպէկրանին:"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Ձայն է արձակում և ցուցադրվում է իջնող վահանակի վրա, կարգավիճակի գոտում և կողպէկրանին:"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Ծանուցումները ցուցադրվում են միայն իջնող վահանակի վրա, որպեսզի դուք չշեղվեք ձեր աշխատանքից: Միշտ անձայն:"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Ցուցադրվում են կարևոր ծանուցումների տակ: Միշտ անձայն:"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Ցուցադրվում են կարևոր ծանուցումների տակ: Միշտ անձայն:"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Ցուցադրվում են կարևոր ծանուցումների տակ: Միշտ անձայն:"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Ծանուցումները ձեր ուշադրությունն են գրավում ազդանշանով և կարգավիճակի գոտում ցուցադրվող պատկերակով: Ցուցադրվում են կողպէկրանին:"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Այս ծանուցումները չեն կարող փոփոխվել:"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Ծանուցումների տվյալ խումբը հնարավոր չէ կարգավորել այստեղ"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Ծանուցումն ուղարկվել է պրոքսի սերվերի միջոցով"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Այս հավելվածն օգտագործում է տեսախցիկը:"</string>
<string name="appops_microphone" msgid="741508267659494555">"Այս հավելվածն օգտագործում է խոսափողը:"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Բացել <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ի ամպիկների կարգավորումներ"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Թույլատրե՞լ ամպիկներ <xliff:g id="APP_NAME">%1$s</xliff:g>-ից։"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Կառավարել"</string>
<string name="no_bubbles" msgid="337101288173078247">"Մերժել"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Թույլատրել"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Հարցնել ավելի ուշ"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Տեղափոխել վերև՝ աջ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Տեղափոխել ներքև՝ ձախ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Տեղափոխել ներքև՝ աջ"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 7031aab..ac4d2c7 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Aktif pada <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Hingga <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema Gelap"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC dinonaktifkan"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC diaktifkan"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Jangan tampilkan lagi"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Hapus semua"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Kelola"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notifikasi senyap"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Hapus semua notifikasi senyap"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifikasi dijeda oleh mode Jangan Ganggu"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Mulai sekarang"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Tidak ada notifikasi"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Layar dipasangi pin"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Ini akan terus ditampilkan sampai Anda melepas pin. Sentuh & tahan tombol Kembali dan Ringkasan untuk melepas pin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Ini akan terus ditampilkan sampai Anda melepas pin. Sentuh & tahan tombol Kembali dan Beranda untuk melepas pin."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Ini akan terus ditampilkan sampai Anda melepas pin. Geser ke atas & tahan untuk melepas pin."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ini akan terus ditampilkan sampai Anda melepas pin. Sentuh dan tahan tombol Ringkasan untuk melepas pin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Ini akan terus ditampilkan sampai Anda melepas pin. Sentuh dan tahan tombol Beranda untuk melepas pin."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Untuk melepas pin layar ini, sentuh & tahan tombol Kembali dan Ringkasan"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Terus tampilkan notifikasi dari aplikasi ini?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Senyap"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Diprioritaskan"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Selalu senyap. Ditampilkan di bayangan pull-down."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Selalu senyap. Ditampilkan di bayangan pull-down & status bar."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Selalu senyap. Ditampilkan di bayangan pull-down & di layar kunci."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Selalu senyap. Ditampilkan di bayangan pull-down, status bar & di layar kunci."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Mengeluarkan suara dan ditampilkan di bayangan pull-down, status bar & di layar kunci."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Membantu Anda berfokus hanya pada notifikasi di bayangan pull-down. Selalu senyap."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Ditampilkan di bawah notifikasi prioritas. Selalu senyap."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Ditampilkan di bawah notifikasi prioritas. Selalu senyap."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Ditampilkan di bawah notifikasi prioritas. Selalu senyap."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Menarik perhatian Anda dengan suara & ikon status bar. Ditampilkan di layar kunci."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Notifikasi ini tidak dapat diubah."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Grup notifikasi ini tidak dapat dikonfigurasi di sini"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notifikasi proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Aplikasi ini sedang menggunakan kamera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Aplikasi ini sedang menggunakan mikrofon."</string>
@@ -765,8 +773,8 @@
<string name="right_keycode" msgid="708447961000848163">"Kode tombol kanan"</string>
<string name="left_icon" msgid="3096287125959387541">"Ikon kiri"</string>
<string name="right_icon" msgid="3952104823293824311">"Ikon kanan"</string>
- <string name="drag_to_add_tiles" msgid="230586591689084925">"Tahan dan tarik untuk menambahkan tile"</string>
- <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Tahan dan tarik untuk mengatur ulang tile"</string>
+ <string name="drag_to_add_tiles" msgid="230586591689084925">"Tahan dan tarik untuk menambahkan kartu"</string>
+ <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Tahan dan tarik untuk mengatur ulang kartu"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"Tarik ke sini untuk menghapus"</string>
<string name="drag_to_remove_disabled" msgid="2390968976638993382">"Anda membutuhkan setidaknya 6 tile"</string>
<string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Buka <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Setelan untuk balon <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Izinkan balon dari <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Kelola"</string>
<string name="no_bubbles" msgid="337101288173078247">"Tolak"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Izinkan"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Nanti saja"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Pindahkan ke kanan atas"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Pindahkan ke kiri bawah"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Pindahkan ke kanan bawah"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 7fe25f8..88b091a 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Kveikt klukkan <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Til klukkan <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Dökkt þema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Slökkt á NFC"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Kveikt á NFC"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ekki sýna þetta aftur"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Hreinsa allt"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Stjórna"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Lágstemmdar tilkynningar"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Hreinsa allar lágstemmdar tilkynningar"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Hlé gert á tilkynningum þar sem stillt er á „Ónáðið ekki“"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Byrja núna"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Engar tilkynningar"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Skjárinn er festur"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Þetta heldur þessu opnu þangað til þú losar það. Haltu fingri á „Til baka“ og „Yfirlit“ til að losa."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Þetta heldur þessu opnu þangað til það er losað. Haltu inni bakkhnappinum og heimahnappinum til að losa."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Þetta heldur þessu opnu þangað til það er losað. Strjúktu upp og haltu inni til að losa."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Þetta heldur þessu opnu þangað til þú losar það. Haltu fingri á „Yfirlit“ til að losa."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Þetta heldur þessu opnu þangað til það er losað. Haltu heimahnappinum inni til að losa."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Til að losa þessa skjámynd skaltu halda inni bakkhnappinum og yfirlitshnappinum"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Sýna áfram tilkynningar frá þessu forriti?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Lágstemmdar"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Í forgangi"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Alltaf án hljóðs. Birtist á fellisvæði."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Alltaf án hljóðs. Birtist í fellisvæði og stöðustiku."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Alltaf án hljóðs. Birtist í fellisvæði og lásskjá."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Alltaf án hljóðs. Birtist á fellisvæði, stöðustiku og lásskjá."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Gefur frá sér hljóð og birtist í fellisvæði, á stöðustiku og lásskjá."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Auðveldar þér að einbeita þér með tilkynningum sem birtast aðeins á fellisvæði. Alltaf án hljóðs."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Birtir tilkynningar með lítinn forgang. Alltaf án hljóðs."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Birtir tilkynningar með lítinn forgang. Alltaf án hljóðs."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Birtir tilkynningar með lítinn forgang. Alltaf án hljóðs."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Fangar athygli þína með hljóði og stöðustikutákni. Sést á lásskjánum."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Ekki er hægt að breyta þessum tilkynningum."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Ekki er hægt að stilla þessar tilkynningar hér"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Staðgengilstilkynning"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Þetta forrit er að nota myndavélina."</string>
<string name="appops_microphone" msgid="741508267659494555">"Þetta forrit er að nota hljóðnemann."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Opna <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Stillingar fyrir blöðrur frá <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Leyfa blöðrur frá <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Stjórna"</string>
<string name="no_bubbles" msgid="337101288173078247">"Hafna"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Leyfa"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Spyrja mig síðar"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Færa efst til hægri"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Færa neðst til vinstri"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Færðu neðst til hægri"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 7248bbb..e1ff5dd 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Dalle <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Fino alle <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema scuro"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC non attiva"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC attiva"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Non mostrare più"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Cancella tutto"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Gestisci"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notifiche senza avvisi"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Cancella tutte le notifiche senza avvisi"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifiche messe in pausa in base alla modalità Non disturbare"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Avvia adesso"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Nessuna notifica"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"La schermata è fissata"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"La schermata rimane visibile finché non viene sganciata. Per sganciarla, tieni premuto Indietro e Panoramica."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"La schermata rimane visibile finché non viene disattivato il blocco su schermo. Per disattivarlo, tocca e tieni premuto Indietro e Home."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Mantiene la visualizzazione fino allo sblocco. Scorri verso l\'alto e tieni premuto per sbloccare."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"La schermata rimane visibile finché non viene sganciata. Per sganciarla, tieni premuto Panoramica."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"La schermata rimane visibile finché non viene disattivato il blocco su schermo. Per disattivarlo, tocca e tieni premuto Home."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Per disattivare il blocco su schermo, tocca e tieni premuti i pulsanti Indietro e Panoramica"</string>
@@ -613,7 +618,7 @@
<string name="do_not_silence" msgid="6878060322594892441">"Non silenziare"</string>
<string name="do_not_silence_block" msgid="4070647971382232311">"Non silenziare e non bloccare"</string>
<string name="tuner_full_importance_settings" msgid="3207312268609236827">"Controlli di gestione delle notifiche"</string>
- <string name="tuner_full_importance_settings_on" msgid="7545060756610299966">"Attiva"</string>
+ <string name="tuner_full_importance_settings_on" msgid="7545060756610299966">"On"</string>
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Off"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"I controlli di gestione delle notifiche ti consentono di impostare un livello di importanza compreso tra 0 e 5 per le notifiche di un\'app. \n\n"<b>"Livello 5"</b>" \n- Mostra in cima all\'elenco di notifiche \n- Consenti l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 4"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 3"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n\n"<b>"Livello 2"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n\n"<b>"Livello 1"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n- Nascondi da schermata di blocco e barra di stato \n- Mostra in fondo all\'elenco di notifiche \n\n"<b>"Livello 0"</b>" \n- Blocca tutte le notifiche dell\'app"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notifiche"</string>
@@ -630,22 +635,25 @@
<string name="inline_block_button" msgid="8735843688021655065">"Blocca"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Continua a mostrare"</string>
<string name="inline_minimize_button" msgid="966233327974702195">"Riduci a icona"</string>
- <string name="inline_silent_button_silent" msgid="6904727667411781466">"Modalità senza avvisi"</string>
+ <string name="inline_silent_button_silent" msgid="6904727667411781466">"Silenziose"</string>
<string name="inline_silent_button_stay_silent" msgid="6308371431217601009">"Continua con notifiche silenziose"</string>
<string name="inline_silent_button_alert" msgid="2449191160203602471">"Modalità invasiva"</string>
<string name="inline_silent_button_keep_alerting" msgid="327696842264359693">"Continua ad avvisare"</string>
<string name="inline_turn_off_notifications" msgid="8635596135532202355">"Disattiva notifiche"</string>
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuare a ricevere notifiche da questa app?"</string>
- <string name="notification_silence_title" msgid="7352089096356977930">"Modalità senza avvisi"</string>
+ <string name="notification_silence_title" msgid="7352089096356977930">"Senza avvisi"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Con priorità"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Sempre silenz. Le notifiche verranno visualizzate nell\'area a discesa."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Sempre silenz. Le notifiche verranno visualizzate nell\'area a discesa e nella barra di stato."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Sempre silenz. Le notifiche verranno visualizzate nell\'area a discesa e sulla schermata di blocco."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Sempre silenz. Le notifiche verranno visualizzate nell\'area a discesa, nella barra di stato e sulla schermata di blocco."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Verranno visualizzate con un suono in area a discesa, barra di stato e schermata di blocco."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Puoi concentrarti perché le notifiche sono visualizzate solo nell\'area a discesa. Sempre silenziose."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Vengono mostrate le notifiche con priorità bassa. Sempre silenziose."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Vengono mostrate le notifiche con priorità bassa. Sempre silenziose."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Vengono mostrate le notifiche con priorità bassa. Sempre silenziose."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Attirano la tua attenzione con un suono e un\'icona nella barra di stato. Le notifiche sono mostrate nella schermata di blocco."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Impossibile modificare queste notifiche."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Qui non è possibile configurare questo gruppo di notifiche"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notifica inviata al proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Questa app sta utilizzando la fotocamera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Questa app sta utilizzando il microfono."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Apri <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Impostazioni per fumetti <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Consentire fumetti da <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Gestisci"</string>
<string name="no_bubbles" msgid="337101288173078247">"Rifiuta"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Consenti"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Ricordamelo più tardi"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Sposta in alto a destra"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Sposta in basso a sinistra"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Sposta in basso a destra"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index aeafdc4..894a30c 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -373,6 +373,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"מופעל בשעה <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"עד <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"עיצוב כהה"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC מושבת"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC מופעל"</string>
@@ -454,6 +456,10 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"אל תציג שוב"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"נקה הכל"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"ניהול"</string>
+ <!-- no translation found for notification_section_header_gentle (8356064473678167305) -->
+ <skip />
+ <!-- no translation found for accessibility_notification_section_header_gentle_clear_all (4270384919249494640) -->
+ <skip />
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"התראות הושהו על ידי מצב \'נא לא להפריע\'"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"התחל כעת"</string>
<string name="empty_shade_text" msgid="708135716272867002">"אין התראות"</string>
@@ -533,6 +539,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"המסך מוצמד"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצנים \'הקודם\' ו\'סקירה\' כדי לבטל את ההצמדה."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצנים \'הקודם\' ו\'דף הבית\' כדי לבטל את ההצמדה."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"נשאר בתצוגה עד לביטול ההצמדה. יש להחליק למעלה ולהחזיק כדי לבטל הצמדה."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצן \'סקירה\' כדי לבטל את ההצמדה."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצן \'דף הבית\' כדי לבטל את ההצמדה."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"כדי לבטל את ההצמדה של מסך זה, יש ללחוץ לחיצה ארוכה על הלחצנים \'הקודם\' ו\'סקירה\'"</string>
@@ -644,14 +651,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"שנמשיך להציג לך התראות מהאפליקציה הזאת?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"התראות מתונות"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"בעדיפות"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"תמיד שקטה. מוצגת בלוח ההתראות הנפתח."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"תמיד שקטה. מוצגת בלוח ההתראות הנפתח ובשורת הסטטוס."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"תמיד שקטה. מוצגת בלוח ההתראות הנפתח ובמסך הנעילה."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"תמיד שקטה. מוצגת בלוח ההתראות הנפתח, בשורת הסטטוס ובמסך הנעילה."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"משמיעה צליל ומוצגת בלוח ההתראות הנפתח, בשורת הסטטוס ובמסך הנעילה."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"עוזרת לריכוז באמצעות הצגת התראות בלוח ההתראות הנפתח בלבד. תמיד שקטה."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"מציגה התראות בעדיפות נמוכה. תמיד שקטה."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"מציגה התראות בעדיפות נמוכה. תמיד שקטה."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"מציגה התראות בעדיפות נמוכה. תמיד שקטה."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"מעוררת תשומת לב באמצעות צלילים וסמל בשורת הסטטוס. מוצגת במסך הנעילה."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"לא ניתן לשנות את ההתראות האלה."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"לא ניתן להגדיר כאן את קבוצת ההתראות הזו"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"התראה דרך שרת proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"האפליקציה הזו משתמשת במצלמה."</string>
<string name="appops_microphone" msgid="741508267659494555">"האפליקציה הזו משתמשת במיקרופון."</string>
@@ -921,6 +931,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"לפתיחת <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"הגדרות בשביל בועות של <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"להתיר ל-<xliff:g id="APP_NAME">%1$s</xliff:g> להציג בועות?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"ניהול"</string>
<string name="no_bubbles" msgid="337101288173078247">"אני לא מרשה"</string>
<string name="yes_bubbles" msgid="668809525728633841">"כן, זה בסדר"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"אחליט מאוחר יותר"</string>
@@ -931,4 +942,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"העברה לפינה הימנית העליונה"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"העברה לפינה השמאלית התחתונה"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"העברה לפינה הימנית התחתונה"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 37e71f7..3f58928 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -67,7 +67,7 @@
<string name="usb_disable_contaminant_detection" msgid="2103905315747120033">"USB を有効にする"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"画面サイズに合わせて拡大"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"画面サイズに合わせて拡大"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"スクリーンショット"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"画面の保存"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"スクリーンショットを保存中..."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"スクリーンショットを保存しています..."</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"スクリーンショットを保存しました"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> に ON"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> まで"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"ダークテーマ"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC は無効です"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC は有効です"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"次回から表示しない"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"すべて消去"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"管理"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"控えめな通知"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"控えめな通知がすべて消去されます"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"サイレント モードにより通知は一時停止中です"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"今すぐ開始"</string>
<string name="empty_shade_text" msgid="708135716272867002">"通知はありません"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"画面が固定されました"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"固定を解除するまで画面が常に表示されるようになります。[戻る] と [最近] を同時に押し続けると固定が解除されます。"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"固定を解除するまで画面が常に表示されるようになります。[戻る] と [ホーム] を同時に押し続けると固定が解除されます。"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"固定を解除するまで常に表示されます。上にスワイプして長押しすると固定が解除されます。"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"固定を解除するまで画面が常に表示されるようになります。[最近] を押し続けると固定が解除されます。"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"固定を解除するまで画面が常に表示されるようになります。[ホーム] を押し続けると固定が解除されます。"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"この画面の固定を解除するには [戻る] ボタンと [最近] ボタンを押し続けます"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"このアプリからの通知を今後も表示しますか?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"通知音なし"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"優先"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"常に通知音は鳴りません。プルダウン シェードに表示されます。"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"常に通知音は鳴りません。プルダウン シェードやステータスバーに表示されます。"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"常に通知音は鳴りません。プルダウン シェードやロック画面に表示されます。"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"常に通知音は鳴りません。プルダウン シェード、ステータスバー、ロック画面に表示されます。"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"通知音が鳴り、プルダウン シェード、ステータスバー、ロック画面に表示されます。"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"プルダウン シェードでのみ通知を確認できます。常に通知音は鳴りません。"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"優先度の低い通知を表示します。常に通知音は鳴りません。"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"優先度の低い通知を表示します。常に通知音は鳴りません。"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"優先度の低い通知を表示します。常に通知音は鳴りません。"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"通知音とステータスバーのアイコンで注意を促します。ロック画面に表示されます。"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"これらの通知は変更できません。"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"このグループの通知はここでは設定できません"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"代理通知"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"このアプリはカメラを使用しています。"</string>
<string name="appops_microphone" msgid="741508267659494555">"このアプリはマイクを使用しています。"</string>
@@ -765,8 +773,8 @@
<string name="right_keycode" msgid="708447961000848163">"右キーコード"</string>
<string name="left_icon" msgid="3096287125959387541">"左アイコン"</string>
<string name="right_icon" msgid="3952104823293824311">"右アイコン"</string>
- <string name="drag_to_add_tiles" msgid="230586591689084925">"タイルを追加するには押し続けながらドラッグ"</string>
- <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"タイルを並べ替えるには押し続けながらドラッグ"</string>
+ <string name="drag_to_add_tiles" msgid="230586591689084925">"タイルを追加するには長押ししてドラッグ"</string>
+ <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"タイルを並べ替えるには長押ししてドラッグ"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"削除するにはここにドラッグ"</string>
<string name="drag_to_remove_disabled" msgid="2390968976638993382">"タイルは 6 個以上必要"</string>
<string name="qs_edit" msgid="2232596095725105230">"編集"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> を開く"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> のふきだしの設定"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> のふきだしを許可しますか?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"管理"</string>
<string name="no_bubbles" msgid="337101288173078247">"拒否"</string>
<string name="yes_bubbles" msgid="668809525728633841">"許可"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"後で確認"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"右上に移動"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"左下に移動"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"右下に移動"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index cefdd73..9d45b3a 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"ჩაირთოს <xliff:g id="TIME">%s</xliff:g>-ზე"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g>-მდე"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"მუქი თემა"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC გათიშულია"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ჩართულია"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"აღარ მაჩვენო"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"ყველას გასუფთავება"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"მართვა"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"მსუბუქი შეტყობინებები"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"ყველა მსუბუქი შეტყობინების გასუფთავება"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"შეტყობინებები დაპაუზდა „არ შემაწუხოთ“ რეჟიმის მეშვეობით"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"დაწყება ახლავე"</string>
<string name="empty_shade_text" msgid="708135716272867002">"შეტყობინებები არ არის."</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"ეკრანი ჩამაგრებულია"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"ამით ის დარჩება ხედში ჩამაგრების მოხსნამდე. ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ „უკან და მიმოხილვა“-ს."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"ამით ის დარჩება ხედში ჩამაგრების მოხსნამდე. ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ „უკან მთავარ გვერდზე“-ს."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"ამით ის დარჩება ხედში ჩამაგრების მოხსნამდე. აუსვით ზემოთ და დააყოვნეთ ჩამაგრების მოსახსნელად."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"ამით ის დარჩება ხედში ჩამაგრების მოხსნამდე. ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ „მიმოხილვა“-ს."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"ამით ის დარჩება ხედში ჩამაგრების მოხსნამდე. ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ „მთავარ გვერდს“."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"ამ ეკრანის ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ ღილაკებს „უკან“ და „მიმოხილვა“"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"გაგრძელდეს შეტყობინებათა ჩვენება ამ აპიდან?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"მსუბუქი"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"პრიორიტეტული"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"ყოველთვის ჩუმი. გამოჩნდება ჩამოსაწევ ფარდაში."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"ყოველთვის ჩუმი. გამოჩნდება ჩამოსაწევ ფარდაში და სტატუსის ზოლში."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"ყოველთვის ჩუმი. გამოჩნდება ჩამოსაწევ ფარდაში და ჩაკეტილ ეკრანზე."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"ყოველთვის ჩუმი. გამოჩნდება ჩამოსაწევ ფარდაში, სტატუსის ზოლში და ჩაკეტილ ეკრანზე."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"გამოსცემს ხმას და გამოჩნდება ჩამოსაწევ ფარდაში, სტატუსის ზოლში და ჩაკეტილ ეკრანზე."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"გეხმარებათ იმ შეტყობინებებზე ყურადღების გამახვილებაში, რომლებიც ჩამოსაწევ ფარდაში ჩანს. ყოველთვის ჩუმი."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"აჩვენებს ნაკლებად პრიორიტეტულ შეტყობინებებს. ყოველთვის ჩუმი."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"აჩვენებს ნაკლებად პრიორიტეტულ შეტყობინებებს. ყოველთვის ჩუმი."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"აჩვენებს ნაკლებად პრიორიტეტულ შეტყობინებებს. ყოველთვის ჩუმი."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"იქცევს თქვენს ყურადღებას ხმით & სტატუსის ზოლის ხატულით. ჩნდება ჩაკეტილ ეკრანზე."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"ამ შეტყობინებების შეცვლა შეუძლებელია."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"შეტყობინებების ამ ჯგუფის კონფიგურირება აქ შეუძლებელია"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"პროქსირებული შეტყობინება"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"ეს აპი იყენებს კამერას."</string>
<string name="appops_microphone" msgid="741508267659494555">"ეს აპი იყენებს მიკროფონს."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ის გახსნა"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"პარამეტრები <xliff:g id="APP_NAME">%1$s</xliff:g> ბუშტებისთვის"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"დაიშვას ბუშტები <xliff:g id="APP_NAME">%1$s</xliff:g>-დან?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"მართვა"</string>
<string name="no_bubbles" msgid="337101288173078247">"უარყოფა"</string>
<string name="yes_bubbles" msgid="668809525728633841">"დაშვება"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"მოგვიანებით მკითხეთ"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"გადაანაცვლეთ ზევით და მარჯვნივ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"ქვევით და მარცხნივ გადატანა"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"გადაანაცვ. ქვემოთ და მარჯვნივ"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 378b30e..e5322e8 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> дейін"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Қараңғы тақырып"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC өшірулі"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC қосулы"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Қайта көрсетпеу"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Барлығын тазалау"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Басқару"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Дыбыссыз хабарландырулар"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Дыбыссыз хабарландырулардың барлығын өшіру"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Хабарландырулар \"Мазаламау\" режимінде кідіртілді"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Қазір бастау"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Хабарландырулар жоқ"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Экран түйрелді"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Экран босатылғанға дейін көрсетіліп тұрады. Оны босату үшін \"Артқа\" және \"Шолу\" түймелерін басып тұрыңыз."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Экран босатылғанға дейін көрсетіліп тұрады. Оны босату үшін \"Артқа\" және \"Негізгі бет\" түймелерін түртіп, ұстап тұрыңыз"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Экран босатылғанға дейін көрсетіліп тұрады. Экранды босату үшін жоғары сырғытып, ұстап тұрыңыз."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Экран босатылғанға дейін көрсетіліп тұрады. Оны босату үшін \"Кері\" түймесін басып тұрыңыз."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Экран босатылғанға дейін көрсетіліп тұрады. Оны босату үшін \"Негізгі бет\" түймесін түртіп, ұстап тұрыңыз."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Бұл экранды босату үшін \"Артқа\" және \"Шолу\" түймелерін түртіп, ұстап тұрыңыз"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Осы қолданбаның хабарландырулары көрсетілсін бе?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Дыбыссыз"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Маңызды"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Үнемі дыбыссыз режимде болады. Хабарландыру ашылмалы панельге шығады."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Үнемі дыбыссыз режимде болады. Хабарландырулар ашылмалы панельге және күй жолағына шығады."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Үнемі дыбыссыз режимде болады. Хабарландырулар ашылмалы панельге немесе құлыптаулы экранға шығады."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Үнемі дыбыссыз режимде болады. Ашылмалы панельге, күй жолағына және құлыптаулы экранға шығады."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Дыбыс шығады және хабарландырулар ашылмалы панельге, күй жолағына және құлыптаулы экранға шығады."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Ашылмалы панельдегі хабарландырулар ғана көрсетіледі. Үнемі дыбыссыз режимде болады."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Маңыздылығы төмен хабарландыруларды көрсетеді. Үнемі дыбыссыз режимде болады."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Маңыздылығы төмен хабарландыруларды көрсетеді. Үнемі дыбыссыз режимде болады."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Маңыздылығы төмен хабарландыруларды көрсетеді. Үнемі дыбыссыз режимде болады."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Дыбыс және күй жолағы белгішесі арқылы ескертеді. Құлыптаулы экранда көрсетіледі."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Бұл хабарландыруларды өзгерту мүмкін емес."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Мұндай хабарландырулар бұл жерде конфигурацияланбайды."</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Прокси-сервер арқылы жіберілген хабарландыру"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Бұл қолданба камераны пайдалануда."</string>
<string name="appops_microphone" msgid="741508267659494555">"Бұл қолданба микрофонды пайдалануда."</string>
@@ -679,7 +687,7 @@
</plurals>
<string name="battery_panel_title" msgid="7944156115535366613">"Батареяны пайдалану"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Зарядтау кезінде Батарея үнемдегіш қол жетімді емес"</string>
- <string name="battery_detail_switch_title" msgid="6285872470260795421">"Батарея үнемдегіш"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Өнімділікті және фондық деректерді азайтады"</string>
<string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> түймесі"</string>
<string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string>
@@ -766,7 +774,7 @@
<string name="left_icon" msgid="3096287125959387541">"Сол жақ белгіше"</string>
<string name="right_icon" msgid="3952104823293824311">"Оң жақ белгіше"</string>
<string name="drag_to_add_tiles" msgid="230586591689084925">"Қажетті элементтерді сүйреп әкеліп қойыңыз"</string>
- <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Бөлшектердің ретін өзгерту үшін оны басып тұрып сүйреңіз"</string>
+ <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Элементтердің ретін өзгерту үшін оларды басып тұрып сүйреңіз"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"Керексіздерін осы жерге сүйреңіз"</string>
<string name="drag_to_remove_disabled" msgid="2390968976638993382">"Кемінде 6 бөлшек қажет"</string>
<string name="qs_edit" msgid="2232596095725105230">"Өңдеу"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасын ашу"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> қалқымалы анықтамаларының параметрлері"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасының қалқымалы анықтамаларына рұқсат етілсін бе?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Басқару"</string>
<string name="no_bubbles" msgid="337101288173078247">"Тыйым салу"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Рұқсат беру"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Кейінірек сұралсын"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Жоғары оң жаққа жылжыту"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Төменгі сол жаққа жылжыту"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Төменгі оң жаққа жылжыту"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index ecdbbe4..58cfbe4 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -323,7 +323,7 @@
<string name="quick_settings_user_label" msgid="5238995632130897840">"ខ្ញុំ"</string>
<string name="quick_settings_user_title" msgid="4467690427642392403">"អ្នកប្រើ"</string>
<string name="quick_settings_user_new_user" msgid="9030521362023479778">"អ្នកប្រើថ្មី"</string>
- <string name="quick_settings_wifi_label" msgid="9135344704899546041">"វ៉ាយហ្វាយ"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"មិនបានតភ្ជាប់"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"គ្មានបណ្ដាញ"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"វ៉ាយហ្វាយបានបិទ"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"បើកនៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"រហូតដល់ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"រចនាប័ទ្មងងឹត"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"បានបិទ NFC"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"បានបើក NFC"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"កុំបង្ហាញម្ដងទៀត"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"សម្អាតទាំងអស់"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"គ្រប់គ្រង"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"ការជូនដំណឹងស្ងាត់ៗ"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"សម្អាតការជូនដំណឹងស្ងាត់ៗទាំងអស់"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"ការជូនដំណឹងបានផ្អាកដោយមុខងារកុំរំខាន"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ចាប់ផ្ដើមឥឡូវ"</string>
<string name="empty_shade_text" msgid="708135716272867002">"គ្មានការជូនដំណឹង"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"អេក្រង់ត្រូវបានភ្ជាប់"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"វានឹងនៅតែបង្ហាញ រហូតទាល់តែអ្នកដកការដៅ។ សូមសង្កត់ប៊ូតុងថយក្រោយ និងប៊ូតុងទិដ្ឋភាពរួមឲ្យជាប់ ដើម្បីដកការដៅ។"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"វានឹងនៅតែបង្ហាញ រហូតទាល់តែអ្នកដកការដៅ។ សូមចុចប៊ូតុងថយក្រោយ និងប៊ូតុងទំព័រដើមឱ្យជាប់ ដើម្បីដកការដៅ។"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"វានឹងនៅតែបង្ហាញ រហូតទាល់តែអ្នកដកការដៅ។ អូសឡើងលើឱ្យជាប់ ដើម្បីដកការដៅ។"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"វានឹងនៅតែបង្ហាញ រហូតទាល់តែអ្នកដកការដៅ។ សូមសង្កត់ប៊ូតុងទិដ្ឋភាពរួមឲ្យជាប់ ដើម្បីដកការដៅ។"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"វានឹងនៅតែបង្ហាញ រហូតទាល់តែអ្នកដកការដៅ។ សូមចុចប៊ូតុងទំព័រដើមឱ្យជាប់ ដើម្បីដកការដៅ។"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"ដើម្បីដកការដៅអេក្រង់នេះ សូមចុចប៊ូតុងថយក្រោយ និងប៊ូតុងទិដ្ឋភាពរួមឱ្យជាប់"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"បន្តបង្ហាញការជូនដំណឹងពីកម្មវិធីនេះ?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"ស្ងាត់ៗ"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"ជាអាទិភាព"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"បិទសំឡេងជានិច្ច។ បង្ហាញនៅក្នុងផ្ទាំងជូនដំណឹងធ្លាក់ចុះ។"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"បិទសំឡេងជានិច្ច។ បង្ហាញនៅក្នុងផ្ទាំងជូនដំណឹងធ្លាក់ចុះ និងរបារស្ថានភាព។"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"បិទសំឡេងជានិច្ច។ បង្ហាញនៅក្នុងផ្ទាំងជូនដំណឹងធ្លាក់ចុះ និងនៅលើអេក្រង់ចាក់សោ។"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"បិទសំឡេងជានិច្ច។ បង្ហាញនៅក្នុងផ្ទាំងជូនដំណឹងធ្លាក់ចុះ របារស្ថានភាព និងនៅលើអេក្រង់ចាក់សោ។"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"បញ្ចេញសំឡេង និងបង្ហាញនៅក្នុងផ្ទាំងជូនដំណឹងធ្លាក់ចុះ របារស្ថានភាព និងនៅលើអេក្រង់ចាក់សោ។"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"ជួយឱ្យអ្នកផ្ដោតតាមរយៈការជូនដំណឹងតែនៅក្នុងផ្ទាំងជូនដំណឹងធ្លាក់ចុះប៉ុណ្ណោះ។ បិទសំឡេងជានិច្ច។"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"បង្ហាញការជូនដំណឹងអាទិភាពខាងក្រោម។ បិទសំឡេងជានិច្ច។"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"បង្ហាញការជូនដំណឹងអាទិភាពខាងក្រោម។ បិទសំឡេងជានិច្ច។"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"បង្ហាញការជូនដំណឹងអាទិភាពខាងក្រោម។ បិទសំឡេងជានិច្ច។"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ធ្វើឱ្យអ្នកចាប់អារម្មណ៍តាមរយៈសំឡេង និងរូបរបារស្ថានភាព។ បង្ហាញនៅលើអេក្រង់ចាក់សោ។"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"មិនអាចកែប្រែការជូនដំណឹងទាំងនេះបានទេ។"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"មិនអាចកំណត់រចនាសម្ព័ន្ធក្រុមការជូនដំណឹងនេះនៅទីនេះបានទេ"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"ការជូនដំណឹងជាប្រូកស៊ី"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"កម្មវិធីនេះកំពុងប្រើកាមេរ៉ា។"</string>
<string name="appops_microphone" msgid="741508267659494555">"កម្មវិធីនេះកំពុងប្រើមីក្រូហ្វូន។"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"បើក <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"ការកំណត់សម្រាប់សារលេចឡើង <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"អនុញ្ញាតសារលេចឡើងពី <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"គ្រប់គ្រង"</string>
<string name="no_bubbles" msgid="337101288173078247">"បដិសេធ"</string>
<string name="yes_bubbles" msgid="668809525728633841">"អនុញ្ញាត"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"សួរខ្ញុំនៅពេលក្រោយ"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"ផ្លាស់ទីទៅផ្នែកខាងលើខាងស្ដាំ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"ផ្លាស់ទីទៅផ្នែកខាងក្រោមខាងឆ្វេង"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"ផ្លាស់ទីទៅផ្នែកខាងក្រោមខាងស្ដាំ"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index ba5c1ed..9f02f78 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> ಸಮಯದಲ್ಲಿ"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> ವರೆಗೂ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"ಡಾರ್ಕ್ ಥೀಮ್"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"ಮತ್ತೊಮ್ಮೆ ತೋರಿಸದಿರು"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸು"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"ನಿರ್ವಹಿಸಿ"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"ಸಾಮಾನ್ಯ ಅಧಿಸೂಚನೆಗಳು"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"ಎಲ್ಲಾ ಸಾಮಾನ್ಯ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೆರವುಗೊಳಿಸಿ"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಎನ್ನುವ ಮೂಲಕ ಅಧಿಸೂಚನೆಗಳನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ಈಗ ಪ್ರಾರಂಭಿಸಿ"</string>
<string name="empty_shade_text" msgid="708135716272867002">"ಯಾವುದೇ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"ಪರದೆಯನ್ನು ಪಿನ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ ಹಾಗೂ ಅನ್ಪಿನ್ ಮಾಡಲು ಅವಲೋಕಿಸಿ."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ ಹಾಗೂ ಅನ್ಪಿನ್ ಮಾಡಲು ಮುಖಪುಟಕ್ಕೆ ಹಿಂತಿರುಗಿ."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಮೇಲೆ ಸ್ವೈಪ್ ಮಾಡಿ ಮತ್ತು ಅನ್ಪಿನ್ ಮಾಡಲು ಹೋಲ್ಡ್ ಮಾಡಿ."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಅನ್ಪಿನ್ ಮಾಡಲು ಅವಲೋಕನವನ್ನು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹೋಲ್ಡ್ ಮಾಡಿ."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಅನ್ಪಿನ್ ಮಾಡಲು ಮುಖಪುಟವನ್ನು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಒತ್ತಿಹಿಡಿಯಿರಿ."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"ಈ ಪರದೆಯನ್ನು ಅನ್ಪಿನ್ ಮಾಡಲು, ಹಿಂದಕ್ಕೆ ಮತ್ತು ಸಮಗ್ರ ನೋಟ ಬಟನ್ಗಳನ್ನು ಸ್ಪರ್ಶಿಸಿ ಒತ್ತಿಹಿಡಿಯಿರಿ"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"ಈ ಅಪ್ಲಿಕೇಶನ್ನಿಂದ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸುತ್ತಲೇ ಇರಬೇಕೆ?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"ಸಾಮಾನ್ಯ"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"ಆದ್ಯತೆಗೊಳಿಸಿದ"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"ಯಾವಾಗಲೂ ನಿಶ್ಯಬ್ದ. ಪುಲ್-ಡೌನ್ ಶೇಡ್ನಲ್ಲಿ ಡಿಸ್ಪ್ಲೇ ಆಗುತ್ತದೆ."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"ಯಾವಾಗಲೂ ನಿಶ್ಯಬ್ದ. ಪುಲ್-ಡೌನ್ ಶೇಡ್ & ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಡಿಸ್ಪ್ಲೇ ಆಗುತ್ತವೆ."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"ಯಾವಾಗಲೂ ನಿಶ್ಯಬ್ದ. ಪುಲ್-ಡೌನ್ ಶೇಡ್ & ಲಾಕ್ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಡಿಸ್ಪ್ಲೇ ಆಗುತ್ತವೆ."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"ಯಾವಾಗಲೂ ನಿಶ್ಯಬ್ದ. ಪುಲ್-ಡೌನ್ ಶೇಡ್, ಸ್ಥಿತಿ ಪಟ್ಟಿ & ಲಾಕ್ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಡಿಸ್ಪ್ಲೇ ಆಗುತ್ತದೆ."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"ಧ್ವನಿ ಮಾಡುತ್ತದೆ ಮತ್ತು ಪುಲ್-ಡೌನ್ ಶೇಡ್, ಸ್ಥಿತಿ ಪಟ್ಟಿ & ಲಾಕ್ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಡಿಸ್ಪ್ಲೇ ಮಾಡುತ್ತದೆ."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"ಪುಲ್-ಡೌನ್ ಶೇಡ್ನಲ್ಲಿರುವ ಅಧಿಸೂಚನೆಗಳ ಕಡೆಗೆ ಮಾತ್ರ ಗಮನಹರಿಸಲು ಸಹಾಯ ಮಾಡುತ್ತದೆ. ಯಾವಾಗಲೂ ನಿಶ್ಯಬ್ದ."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"ಪ್ರಾಶಸ್ತ್ಯದ ಅಧಿಸೂಚನೆಗಳ ಕೆಳಗೆ ಪ್ರದರ್ಶಿತವಾಗುತ್ತದೆ. ಯಾವಾಗಲೂ ನಿಶ್ಯಬ್ದ."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"ಪ್ರಾಶಸ್ತ್ಯದ ಅಧಿಸೂಚನೆಗಳ ಕೆಳಗೆ ಪ್ರದರ್ಶಿತವಾಗುತ್ತದೆ. ಯಾವಾಗಲೂ ನಿಶ್ಯಬ್ದ."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"ಪ್ರಾಶಸ್ತ್ಯದ ಅಧಿಸೂಚನೆಗಳ ಕೆಳಗೆ ಪ್ರದರ್ಶಿತವಾಗುತ್ತದೆ. ಯಾವಾಗಲೂ ನಿಶ್ಯಬ್ದ."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ಧ್ವನಿ ಮತ್ತು ಸ್ಥಿತಿ ಪಟ್ಟಿ ಐಕಾನ್ ಮೂಲಕ ನಿಮ್ಮ ಗಮನವನ್ನು ಸೆಳೆಯುತ್ತದೆ. ಲಾಕ್ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ತೋರಿಸುತ್ತದೆ."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"ಈ ಗುಂಪಿನ ಅಧಿಸೂಚನೆಗಳನ್ನು ಇಲ್ಲಿ ಕಾನ್ಫಿಗರ್ ಮಾಡಲಾಗಿರುವುದಿಲ್ಲ"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"ಪ್ರಾಕ್ಸಿ ಮಾಡಿದ ಅಧಿಸೂಚನೆಗಳು"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುತ್ತಿದೆ."</string>
<string name="appops_microphone" msgid="741508267659494555">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು ಬಳಸುತ್ತಿದೆ."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಬಬಲ್ಗಳಿಗಾಗಿ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್ನ ಬಬಲ್ಗಳನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"ನಿರ್ವಹಿಸಿ"</string>
<string name="no_bubbles" msgid="337101288173078247">"ನಿರಾಕರಿಸಿ"</string>
<string name="yes_bubbles" msgid="668809525728633841">"ಅನುಮತಿಸಿ"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"ನನ್ನನ್ನು ಆನಂತರ ಕೇಳಿ"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"ಬಲ ಮೇಲ್ಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"ಸ್ಕ್ರೀನ್ನ ಎಡ ಕೆಳಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"ಕೆಳಗಿನ ಬಲಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 886eaa5..e6d3283 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -223,7 +223,7 @@
<string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"비행기 모드가 사용 중지되었습니다."</string>
<string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"비행기 모드를 사용합니다."</string>
<string name="accessibility_quick_settings_dnd_none_on" msgid="2960643943620637020">"모두 음소거"</string>
- <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3357131899365865386">"알람만"</string>
+ <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3357131899365865386">"알람만 허용"</string>
<string name="accessibility_quick_settings_dnd" msgid="5555155552520665891">"방해 금지 모드"</string>
<string name="accessibility_quick_settings_dnd_changed_off" msgid="2757071272328547807">"방해 금지 모드가 사용 중지되었습니다."</string>
<string name="accessibility_quick_settings_dnd_changed_on" msgid="6808220653747701059">"방해 금지 모드가 사용 설정되었습니다."</string>
@@ -292,8 +292,8 @@
<string name="ethernet_label" msgid="7967563676324087464">"이더넷"</string>
<string name="quick_settings_header_onboarding_text" msgid="8030309023792936283">"추가 옵션을 보려면 아이콘을 길게 터치하세요."</string>
<string name="quick_settings_dnd_label" msgid="7112342227663678739">"방해 금지 모드"</string>
- <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"중요 알림만"</string>
- <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"알람만"</string>
+ <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"중요 알림만 허용"</string>
+ <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"알람만 허용"</string>
<string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"모두 차단"</string>
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"블루투스"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"블루투스(<xliff:g id="NUMBER">%d</xliff:g>개의 기기)"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>에"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g>까지"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"어두운 테마"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC 사용 중지됨"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC 사용 설정됨"</string>
@@ -399,8 +401,8 @@
<string name="camera_hint" msgid="7939688436797157483">"카메라를 사용하려면 아이콘에서 스와이프하세요."</string>
<string name="interruption_level_none_with_warning" msgid="5114872171614161084">"전체 무음입니다. 이렇게 하면 스크린 리더도 무음으로 설정됩니다."</string>
<string name="interruption_level_none" msgid="6000083681244492992">"모두 차단"</string>
- <string name="interruption_level_priority" msgid="6426766465363855505">"중요 알림만"</string>
- <string name="interruption_level_alarms" msgid="5226306993448328896">"알람만"</string>
+ <string name="interruption_level_priority" msgid="6426766465363855505">"중요 알림만 허용"</string>
+ <string name="interruption_level_alarms" msgid="5226306993448328896">"알람만 허용"</string>
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"모두\n차단"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"중요 알림만\n허용"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"알람만\n"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"다시 표시 안함"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"모두 지우기"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"관리"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"조용한 알림"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"조용한 알림 모두 삭제"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"방해 금지 모드로 일시중지된 알림"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"시작하기"</string>
<string name="empty_shade_text" msgid="708135716272867002">"알림 없음"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"화면 고정됨"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"고정 해제할 때까지 계속 표시됩니다. 고정 해제하려면 뒤로 및 최근 사용을 길게 터치하세요."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"고정 해제할 때까지 계속 표시됩니다. 고정 해제하려면 뒤로 및 홈을 길게 터치하세요."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"고정 해제할 때까지 계속 표시됩니다. 고정 해제하려면 위로 스와이프한 다음 탭한 상태를 유지하세요."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"고정 해제할 때까지 계속 표시됩니다. 고정 해제하려면 최근 사용을 길게 터치하세요."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"고정 해제할 때까지 계속 표시됩니다. 고정 해제하려면 홈을 길게 터치하세요."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"이 화면을 고정 해제하려면 뒤로 및 최근 사용 버튼을 길게 터치하세요."</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"이 앱의 알림을 계속 표시하시겠습니까?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"조용히 표시됨"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"우선순위 지정됨"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"항상 음소거됩니다. 풀다운 창에 표시됩니다."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"항상 음소거됩니다. 풀다운 창 및 상태 표시줄에 표시됩니다."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"항상 음소거됩니다. 풀다운 창 및 잠금 화면에 표시됩니다."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"항상 음소거됩니다. 풀다운 창, 상태 표시줄, 잠금 화면에 표시됩니다."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"풀다운 창, 상태 표시줄, 잠금 화면에 소리와 함께 표시됩니다."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"풀다운 창에만 알림을 표시하여 집중에 방해가 되지 않습니다. 항상 음소거됩니다."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"우선순위 알림 아래에 표시됩니다. 항상 음소거됩니다."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"우선순위 알림 아래에 표시됩니다. 항상 음소거됩니다."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"우선순위 알림 아래에 표시됩니다. 항상 음소거됩니다."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"소리 및 상태 표시줄 아이콘으로 주의를 끕니다. 잠금 화면에 표시됩니다."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"이 알림은 수정할 수 없습니다."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"이 알림 그룹은 여기에서 설정할 수 없습니다."</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"프록시를 통한 알림"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"앱이 카메라를 사용 중입니다."</string>
<string name="appops_microphone" msgid="741508267659494555">"앱이 마이크를 사용 중입니다."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> 열기"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> 알림 풍선 설정"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g>의 알림 풍선을 허용하시겠습니까?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"관리"</string>
<string name="no_bubbles" msgid="337101288173078247">"거부"</string>
<string name="yes_bubbles" msgid="668809525728633841">"허용"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"나중에 알림"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"오른쪽 상단으로 이동"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"왼쪽 하단으로 이동"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"오른쪽 하단으로 이동"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index b69dc24..ff421cb 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -292,7 +292,7 @@
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_header_onboarding_text" msgid="8030309023792936283">"Кошумча параметрлерди ачуу үчүн сүрөтчөлөрдү басып, кармап туруңуз"</string>
<string name="quick_settings_dnd_label" msgid="7112342227663678739">"Тынчымды алба"</string>
- <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Шашылыш эскертмелер гана"</string>
+ <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Шашылыш билдирүүлөр гана"</string>
<string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Ойготкуч гана"</string>
<string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"Тымтырс"</string>
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Саат <xliff:g id="TIME">%s</xliff:g> күйөт"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> чейин"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Түнкү режим"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC өчүрүлгөн"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC иштетилген"</string>
@@ -399,7 +401,7 @@
<string name="camera_hint" msgid="7939688436797157483">"Сүрөтчөнү серпип камерага өтүңүз"</string>
<string name="interruption_level_none_with_warning" msgid="5114872171614161084">"Толук жымжырттык талап кылынат. Бул экрандагыны окугучтарды да тынчтандырат."</string>
<string name="interruption_level_none" msgid="6000083681244492992">"Тымтырс"</string>
- <string name="interruption_level_priority" msgid="6426766465363855505">"Шашылыш эскертмелер гана"</string>
+ <string name="interruption_level_priority" msgid="6426766465363855505">"Шашылыш билдирүүлөр гана"</string>
<string name="interruption_level_alarms" msgid="5226306993448328896">"Ойготкуч гана"</string>
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Тым-\nтырс"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Артыкчылыктуу\nгана"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Экинчи көрсөтүлбөсүн"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Бардыгын тазалап салуу"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Башкаруу"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Маанилүү эмес билдирмелер"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Бардык маанилүү эмес билдирмелерди тазалоо"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\"Тынчымды алба\" режиминде билдирмелер тындырылды"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Азыр баштоо"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Билдирме жок"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Экран кадалган"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Артка\" жана \"Карап чыгуу\" баскычтарын басып, кармап туруңуз."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Артка\" жана \"Башкы бет\" баскычтарын басып, кармап туруңуз."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн өйдө сүрүп, коё бербей басып туруңуз."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Карап чыгуу\" баскычын басып, кармап туруңуз."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Башкы бет\" баскычын басып, кармап туруңуз."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Бул экранды бошотуу үчүн \"Артка\" жана \"Сереп салуу\" баскычтарын басып, кармап туруңуз"</string>
@@ -620,7 +625,7 @@
<string name="notification_channel_disabled" msgid="344536703863700565">"Мындан ары бул эскертмелер сизге көрсөтүлбөйт"</string>
<string name="notification_channel_minimized" msgid="1664411570378910931">"Бул эскертмелер кичирейтилет"</string>
<string name="notification_channel_silenced" msgid="2877199534497961942">"Бул билдирмелер үнсүз көрсөтүлөт"</string>
- <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Бул билдирмелер үн менен эскертилет"</string>
+ <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Бул билдирмелер тууралуу кабарлап турабыз"</string>
<string name="inline_blocking_helper" msgid="3055064577771478591">"Адатта мындай эскертмелерди өткөрүп жибересиз. \nАлар көрсөтүлө берсинби?"</string>
<string name="inline_done_button" msgid="492513001558716452">"Бүттү"</string>
<string name="inline_ok_button" msgid="975600017662930615">"Колдонуу"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Бул колдонмонун эскертмелери көрсөтүлө берсинби?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Маанилүү эмес"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Маанилүү"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Ар дайым үнсүз. Тигинен жайгашкан экранда чагылдырылат."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Ар дайым үнсүз. Тигинен жайгашкан экранда жана абал тилкесинде чагылдырылат."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Ар дайым үнсүз. Тигинен жайгашкан экранда жана кулпуланган экранда чагылдырылат."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Ар дайым үнсүз. Тигинен жайгашкан экранда, абал тилкесинде жана кулпуланган экранда чагылдырылат."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Үнү чыгат, ошондой эле тигинен жайгашкан экранда, абал тилкесинде жана кулпуланган экранда чагылдырылат."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Тигинен жайгашкан экрандагы билдирмелерге гана фокустоого жардам берет. Ар дайым үнсүз."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Маанилүү билдирмелердин ылдый жагында чагылдырылат. Ар дайым үнсүз."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Маанилүү билдирмелердин ылдый жагында чагылдырылат. Ар дайым үнсүз."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Маанилүү билдирмелердин ылдый жагында чагылдырылат. Ар дайым үнсүз."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Үн чыгаруу жана абал тилкесиндеги сүрөтчө менен көңүлүңүздү бурат. Кулпуланган экранда көрсөтүлөт."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Бул билдирмелерди өзгөртүүгө болбойт."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Бул билдирмелердин тобун бул жерде конфигурациялоого болбойт"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Прокси билдирмеси"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Бул колдонмо камераны колдонууда."</string>
<string name="appops_microphone" msgid="741508267659494555">"Бул колдонмо микрофонду колдонууда."</string>
@@ -763,8 +771,8 @@
<string name="accessibility_key" msgid="5701989859305675896">"Ыңгайлаштырылган чабыттоо баскычы"</string>
<string name="left_keycode" msgid="2010948862498918135">"Сол жактагы баскыч коду"</string>
<string name="right_keycode" msgid="708447961000848163">"Оң жактагы баскыч коду"</string>
- <string name="left_icon" msgid="3096287125959387541">"Сол жактагы сүрөтчө"</string>
- <string name="right_icon" msgid="3952104823293824311">"Оң жактагы сүрөтчө"</string>
+ <string name="left_icon" msgid="3096287125959387541">"¨Солго¨ сүрөтчөсү"</string>
+ <string name="right_icon" msgid="3952104823293824311">"¨Оңго¨ сүрөтчөсү"</string>
<string name="drag_to_add_tiles" msgid="230586591689084925">"Керектүү элементтерди сүйрөп келиңиз"</string>
<string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Элементтердин иретин өзгөртүү үчүн кармап туруп, сүйрөңүз"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"Алып салуу үчүн бул жерге сүйрөңүз"</string>
@@ -774,12 +782,12 @@
<string-array name="clock_options">
<item msgid="5965318737560463480">"Сааттар, мүнөттөр жана секунддар"</item>
<item msgid="1427801730816895300">"Сааттар жана мүнөттөр (демейки шартта)"</item>
- <item msgid="3830170141562534721">"Бул сөлөкөт көрсөтүлбөсүн"</item>
+ <item msgid="3830170141562534721">"Бул сүрөтчө көрсөтүлбөсүн"</item>
</string-array>
<string-array name="battery_options">
<item msgid="3160236755818672034">"Ар дайым пайызы көрсөтүлсүн"</item>
<item msgid="2139628951880142927">"Кубаттоо учурунда пайызы көрсөтүлсүн (демейки)"</item>
- <item msgid="3327323682209964956">"Бул сөлөкөт көрсөтүлбөсүн"</item>
+ <item msgid="3327323682209964956">"Бул сүрөтчө көрсөтүлбөсүн"</item>
</string-array>
<string name="tuner_low_priority" msgid="1325884786608312358">"Анча маанилүү эмес билдирменин сүрөтчөлөрүн көрсөтүү"</string>
<string name="other" msgid="4060683095962566764">"Башка"</string>
@@ -853,7 +861,7 @@
<string name="tuner_right" msgid="6222734772467850156">"Оңго"</string>
<string name="tuner_menu" msgid="191640047241552081">"Меню"</string>
<string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу"</string>
- <string name="notification_channel_alerts" msgid="4496839309318519037">"Эскертүүлөр"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"Шашылыш билдирүүлөр"</string>
<string name="notification_channel_battery" msgid="5786118169182888462">"Батарея"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоттор"</string>
<string name="notification_channel_general" msgid="4525309436693914482">"Жалпы билдирүүлөр"</string>
@@ -879,8 +887,8 @@
<string name="qs_dnd_replace" msgid="8019520786644276623">"Алмаштыруу"</string>
<string name="running_foreground_services_title" msgid="381024150898615683">"Фондо иштеп жаткан колдонмолор"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Батареянын кубаты жана трафиктин көлөмү жөнүндө билүү үчүн таптап коюңуз"</string>
- <string name="mobile_data_disable_title" msgid="1068272097382942231">"Мобилдик Интернет өчүрүлсүнбү?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"<xliff:g id="CARRIER">%s</xliff:g> байланыш оператору аркылуу дайындарга же Интернетке кирүү мүмкүнчүлүгүңүз болбойт. Интернетке Wi-Fi аркылуу гана кирүү мүмкүн."</string>
+ <string name="mobile_data_disable_title" msgid="1068272097382942231">"Мобилдик Интернетти өчүрөсүзбү?"</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"<xliff:g id="CARRIER">%s</xliff:g> байланыш оператору аркылуу дайындарга же Интернетке кирүү мүмкүнчүлүгүңүз болбойт. Интернетке Wi-Fi аркылуу гана кире аласыз."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"байланыш операторуңуз"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Уруксат берүү сурамыңыз көрүнбөй калгандыктан, Жөндөөлөр жообуңузду ырастай албай жатат."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> колдонмосуна <xliff:g id="APP_2">%2$s</xliff:g> үлгүлөрүн көрсөтүүгө уруксат берилсинби?"</string>
@@ -910,7 +918,8 @@
<string name="restart_button_description" msgid="2035077840254950187">"Бул колдонмону өчүрүп күйгүзүп, толук экранга өтүү үчүн таптап коюңуз."</string>
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосун ачуу"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> көбүктөрүнүн жөндөөлөрү"</string>
- <string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунун көбүктөрүнө уруксат берилсинби?"</string>
+ <string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунун калкып чыкма билдирмелерине уруксат бересизби?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Башкаруу"</string>
<string name="no_bubbles" msgid="337101288173078247">"Жок"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Уруксат берүү"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Кийинчерээк суралсын"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Жогорку оң жакка жылдырыңыз"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Төмөнкү сол жакка жылдыруу"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Төмөнкү оң жакка жылдырыңыз"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index baeb551..5acef8d 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -118,7 +118,7 @@
<string name="cancel" msgid="6442560571259935130">"ຍົກເລີກ"</string>
<string name="biometric_dialog_confirm" msgid="6468457350041712674">"ຢືນຢັນ"</string>
<string name="biometric_dialog_try_again" msgid="1900185172633183201">"ລອງໃໝ່"</string>
- <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
+ <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ແຕະໃສ່ເຊັນເຊີລາຍນິ້ວມື"</string>
<string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ໄອຄອນລາຍນິ້ວມື"</string>
<string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ກຳລັງຊອກຫາທ່ານ…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"ໄອຄອນໃບໜ້າ"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"ເປີດຕອນ <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"ຈົນກວ່າຈະຮອດ <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"ຮູບແບບສີສັນມືດ"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"ບໍ່ຕ້ອງສະແດງອີກ"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"ລຶບລ້າງທັງໝົດ"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"ຈັດການ"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"ການແຈ້ງເຕືອນສຸພາບ"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"ລຶບລ້າງການແຈ້ງເຕືອນແບບສຸພາບ"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"ຢຸດການແຈ້ງເຕືອນໂດຍໂໝດຫ້າມລົບກວນແລ້ວ"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ເລີ່ມດຽວນີ້"</string>
<string name="empty_shade_text" msgid="708135716272867002">"ບໍ່ມີການແຈ້ງເຕືອນ"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"ປັກໝຸດໜ້າຈໍແລ້ວ"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກມຸດ. ໃຫ້ແຕະປຸ່ມກັບຄືນ ແລະ ປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກມຸດ."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກໝຸດ. ໃຫ້ແຕະປຸ່ມກັບຄືນ ແລະ ປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກໝຸດ."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"ນີ້ຈະເຮັດໃຫ້ມັນຢູ່ໃນມຸມມອງຈົນກວ່າທ່ານຈະເຊົາປັກໝຸດ. ປັດຂຶ້ນຄ້າງໄວ້ເພື່ອເຊົາປັກໝຸດ."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກມຸດ. ໃຫ້ແຕະປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກມຸດ."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກໝຸດ. ໃຫ້ແຕະປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກໝຸດ."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"ເພື່ອຍົກເລີກການປັກໝຸດໜ້າຈໍນີ້, ໃຫ້ແຕະປຸ່ມກັບຄືນ ແລະ ປຸ່ມພາບຮວມຄ້າງໄວ້"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"ສະແດງການແຈ້ງເຕືອນຈາກແອັບນີ້ຕໍ່ໄປບໍ?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"ສຸພາບ"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"ສຳຄັນ"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"ປິດສຽງຕະຫຼອດ. ສະແດງໃນແຖບແບບເລື່ອນລົງ."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"ປິດສຽງຕະຫຼອດ. ສະແດງໃນແຖບແບບເລື່ອນລົງ ແລະ ແຖບສະຖານະ."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"ປິດສຽງຕະຫຼອດ. ສະແດງໃນແຖບແບບດຶງລົງ ແລະ ໃນໜ້າຈໍລັອກ."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"ປິດສຽງຕະຫຼອດ. ສະແດງໃນແຖບແບບເລື່ອນລົງ, ແຖບສະຖານະ ແລະ ຢູ່ໜ້າຈໍລັອກ."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"ເປີດສຽງ ແລະ ສະແດງໃນແຖບແບບເລື່ອນລົງ, ແຖບສະຖານະ ແລະ ຢູ່ໜ້າຈໍລັອກ."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"ຊ່ວຍທ່ານມີສະມາທິກກັບການແຈ້ງເຕືອນສະເພາະໃນແຖບເລື່ອນລົງເທົ່ານັ້ນ. ປິດສຽງຕະຫຼອດ."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"ສະແດງການແຈ້ງເຕືອນທີ່ຄວາມສຳຄັນຕ່ຳລົງ. ປິດສຽງຕະຫຼອດ."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"ສະແດງການແຈ້ງເຕືອນທີ່ຄວາມສຳຄັນຕ່ຳລົງ. ປິດສຽງຕະຫຼອດ."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"ສະແດງການແຈ້ງເຕືອນທີ່ຄວາມສຳຄັນຕ່ຳລົງ. ປິດສຽງຕະຫຼອດ."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ດຶງຄວາມສົນໃຈຂອງທ່ານດ້ວຍສຽງ ແລະ ໄອຄອນແຖບສະຖານະ. ສະແດງຢູ່ໜ້າຈໍລັອກ."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"ບໍ່ສາມາດແກ້ໄຂການແຈ້ງເຕືອນເຫຼົ່ານີ້ໄດ້."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"ບໍ່ສາມາດຕັ້ງຄ່າກຸ່ມການແຈ້ງເຕືອນນີ້ຢູ່ບ່ອນນີ້ໄດ້"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"ການແຈ້ງເຕືອນແບບພຣັອກຊີ"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"ແອັບນີ້ກຳລັງໃຊ້ກ້ອງຢູ່."</string>
<string name="appops_microphone" msgid="741508267659494555">"ແອັບນີ້ກຳລັງໃຊ້ໄມໂຄຣໂຟນຢູ່."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"ເປີດ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"ການຕັ້ງຄ່າສຳລັບ bubble <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"ອະນຸຍາດໃຫ້ມີ bubbles ຈາກ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"ຈັດການ"</string>
<string name="no_bubbles" msgid="337101288173078247">"ປະຕິເສດ"</string>
<string name="yes_bubbles" msgid="668809525728633841">"ອະນຸຍາດ"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"ຖາມຂ້ອຍໃນພາຍຫຼັງ"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"ຍ້າຍຂວາເທິງ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"ຍ້າຍຊ້າຍລຸ່ມ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"ຍ້າຍຂວາລຸ່ມ"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 3dad73d..3bb4212 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -373,6 +373,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Iki <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tamsioji tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"ALR"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"ALR išjungtas"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"ALR įjungtas"</string>
@@ -454,6 +456,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Daugiau neberodyti"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Viską išvalyti"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Tvarkyti"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Taktiški pranešimai"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Išvalyti visus taktiškus pranešimus"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Pranešimai pristabdyti naudojant netrukdymo režimą"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Pradėti dabar"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Nėra įspėjimų"</string>
@@ -533,6 +537,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekranas prisegtas"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Tai bus rodoma, kol atsegsite. Palieskite ir palaikykite „Atgal“ ir „Apžvalga“, kad atsegtumėte."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Tai bus rodoma, kol atsegsite. Palieskite ir palaikykite „Atgal“ ir „Pagrindinis ekranas“, kad atsegtumėte."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Tai bus rodoma, kol atsegsite. Perbraukite aukštyn ir palaikykite, kad atsegtumėte."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Tai bus rodoma, kol atsegsite. Palieskite ir palaikykite „Apžvalga“, kad atsegtumėte."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Tai bus rodoma, kol atsegsite. Palieskite ir palaikykite „Pagrindinis ekranas“, kad atsegtumėte."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Kad atsegtumėte šį ekraną, palieskite ir palaikykite mygtukus „Atgal“ ir „Apžvalga“"</string>
@@ -644,14 +649,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Toliau rodyti iš šios programos gautus pranešimus?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Netrikdantys"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Pirmenybiniai"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Visada nutildyti. Pateikiama išskleidžiamajame skydelyje."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Visada nutildyti. Pateikiama išskleidžiamajame skydelyje ir būsenos juostoje."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Visada nutildyti. Pateikiama išskleidžiamajame skydelyje ir užrakinimo ekrane."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Visada nutildyti. Pateikiama išskleidžiamajame skydelyje, būsenos juostoje ir užrakinimo ekrane."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Leidžiamas garsas ir pateikiama išskleidžiamajame skydelyje, būsenos juostoje bei užrakinimo ekrane."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Padeda susikaupti, nes pranešimai pateikiami tik išskleidžiamajame skydelyje. Visada nutildyti."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Pateikiami po prioritetiniais pranešimais. Visada nutildyti."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Pateikiami po prioritetiniais pranešimais. Visada nutildyti."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Pateikiami po prioritetiniais pranešimais. Visada nutildyti."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Dėmesį atkreipia garsas ir būsenos juostos piktograma. Rodomi užrakintame ekrane."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Šių pranešimų keisti negalima."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Šios grupės pranešimai čia nekonfigūruojami"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Per tarpinį serverį gautas pranešimas"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Ši programa naudoja fotoaparatą."</string>
<string name="appops_microphone" msgid="741508267659494555">"Ši programa naudoja mikrofoną."</string>
@@ -921,6 +929,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Atidaryti „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ debesėlių nustatymai"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Leisti programos „<xliff:g id="APP_NAME">%1$s</xliff:g>“ debesėlius?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Tvarkyti"</string>
<string name="no_bubbles" msgid="337101288173078247">"Atmesti"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Leisti"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Paklausti vėliau"</string>
@@ -931,4 +940,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Perkelti į viršų dešinėje"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Perkelti į apačią kairėje"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Perkelti į apačią dešinėje"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 8893328..2b529ae7 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -371,6 +371,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Līdz <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tumšais motīvs"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ir atspējoti"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ir iespējoti"</string>
@@ -451,6 +453,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Vairs nerādīt"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Dzēst visu"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Pārvaldīt"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Neuzkrītoši paziņojumi"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Notīrīt visus neuzkrītošos paziņojumus"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Paziņojumi pārtraukti, izmantojot iestatījumu “Netraucēt”"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Sākt tūlīt"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Nav paziņojumu"</string>
@@ -530,6 +534,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekrāns ir piesprausts"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties pogām Atpakaļ un Pārskats un turiet tās."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties pogām “Atpakaļ” un “Sākums” un turiet tās."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Velciet augšup un turiet to, lai atspraustu."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties pogai Pārskats un turiet to."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties pogai “Sākums” un turiet to."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Lai atspraustu šo ekrānu, pieskarieties pogām “Atpakaļ” un “Pārskats” un turiet tās."</string>
@@ -641,14 +646,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Vai turpināt rādīt paziņojumus no šīs lietotnes?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Neuzkrītoši"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritāri"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Vienmēr kluss. Paziņojumi tiek rādīti nolaižamajā panelī."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Vienmēr kluss. Paziņojumi tiek rādīti nolaižamajā panelī un statusa joslā."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Vienmēr kluss. Paziņojumi tiek rādīti nolaižamajā panelī un bloķēšanas ekrānā."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Vienmēr kluss. Paziņojumi tiek rādīti nolaižamajā panelī, statusa joslā un bloķēšanas ekrānā."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Paziņojumi tiek rādīti nolaižamajā panelī, statusa joslā un bloķēšanas ekrānā ar skaņas signālu."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Lai netraucētu jums koncentrēties, paziņojumi tiek rādīti tikai nolaižamajā panelī. Vienmēr bez skaņas."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Tiek rādīts zem prioritārajiem paziņojumiem. Vienmēr bez skaņas."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Tiek rādīts zem prioritārajiem paziņojumiem. Vienmēr bez skaņas."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Tiek rādīts zem prioritārajiem paziņojumiem. Vienmēr bez skaņas."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Lai piesaistītu jūsu uzmanību, tiek atskaņots signāls un tiek rādīta statusa joslas ikona. Paziņojums ir redzams bloķēšanas ekrānā."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Šos paziņojumus nevar modificēt."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Šeit nevar konfigurēt šo paziņojumu grupu."</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Starpniekservera paziņojums"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Šajā lietotnē tiek izmantota kamera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Šajā lietotnē tiek izmantots mikrofons."</string>
@@ -916,6 +924,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Atvērt lietotni <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> burbuļu iestatījumi"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Vai atļaut burbuļus no lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Pārvaldīt"</string>
<string name="no_bubbles" msgid="337101288173078247">"Neatļaut"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Atļaut"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Pajautāt vēlāk"</string>
@@ -926,4 +935,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Pārvietot augšpusē pa labi"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Pārvietot apakšpusē pa kreisi"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Pārvietot apakšpusē pa labi"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index d21d12b..69d648b 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ќе се вклучи во <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Темна тема"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC е оневозможено"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC е овозможено"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Не покажувај повторно"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Исчисти сè"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Управувајте"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Нежни известувања"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Исчисти ги сите нежни известувања"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Известувањата се паузирани од „Не вознемирувај“"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Започни сега"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Нема известувања"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Екранот е прикачен"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Ќе се гледа сѐ додека не го откачите. Допрете и држете „Назад“ и „Краток преглед“ за откачување."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Ќе се гледа сѐ додека не го откачите. Допрете и задржете „Назад“ и „Почетен екран“ за откачување."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Ќе се гледа сѐ додека не го откачите. Лизгајте нагоре и задржете за откачување."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ќе се гледа сѐ додека не го откачите. Допрете и држете „Краток преглед“ за откачување."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Ќе се гледа сѐ додека не го откачите. Допрете и задржете „Почетен екран“ за откачување."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"За откачување на екранов, допрете и задржете ги копчињата „Назад“ и „Краток преглед“"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Дали да продолжат да се прикажуваат известувања од апликацијава?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Тивко"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Приоритетно"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Секогаш безгласно. Се прикажува во паѓачки список во сенка."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Секогаш безгласно. Се прикажува во паѓачки список во сенка и статусна лента."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Секогаш безгласно. Се прикажува во паѓачки список во сенка и на заклучен екран."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Секогаш безгласно. Се прикажува во паѓачки список во сенка, статусна лента и на заклучен екран."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Пушта звук и се прикажува во паѓачки список во сенка, статусна лента и на заклучен екран."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Не ви го одвлекува вниманието прикажувајќи известувања само во списокот со известувања. Секогаш безгласно."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Се прикажува под приоритетните известувања. Секогаш безгласно."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Се прикажува под приоритетните известувања. Секогаш безгласно."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Се прикажува под приоритетните известувања. Секогаш безгласно."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Ви го привлекува вниманието со звук и икона во статусната лента. Се прикажува на заклучен екран."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Овие известувања не може да се изменат"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Оваа група известувања не може да се конфигурира тука"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Известување преку прокси"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Апликацијава ја користи камерата."</string>
<string name="appops_microphone" msgid="741508267659494555">"Апликацијава го користи микрофонот."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Отворете ја <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Поставки за баланчињата на <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Да се дозволат балончиња од <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Управување"</string>
<string name="no_bubbles" msgid="337101288173078247">"Одбиј"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Дозволи"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Прашај ме подоцна"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Премести горе десно"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Премести долу лево"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Премести долу десно"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index c363bfa..0cc0aef 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -306,8 +306,8 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="4930931771490695395">"ശ്രവണ സഹായികൾ"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="4551281899312150640">"ഓണാക്കുന്നു…"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"തെളിച്ചം"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"സ്ക്രീൻ സ്വമേധയാ തിരിയുക"</string>
- <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"സ്ക്രീൻ സ്വയമേ തിരിക്കുക"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"സ്ക്രീൻ സ്വയമേവ തിരിയുക"</string>
+ <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"സ്ക്രീൻ സ്വയമേവ തിരിക്കുക"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"<xliff:g id="ID_1">%s</xliff:g> മോഡ്"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"റൊട്ടേഷൻ ലോക്കുചെയ്തു"</string>
<string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"പോർട്രെയ്റ്റ്"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>-ന്"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> വരെ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"ഇരുണ്ട തീം"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC പ്രവർത്തനക്ഷമമാക്കി"</string>
@@ -448,6 +450,10 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"വീണ്ടും കാണിക്കരുത്"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"എല്ലാം മായ്ക്കുക"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"മാനേജ് ചെയ്യുക"</string>
+ <!-- no translation found for notification_section_header_gentle (8356064473678167305) -->
+ <skip />
+ <!-- no translation found for accessibility_notification_section_header_gentle_clear_all (4270384919249494640) -->
+ <skip />
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\'ശല്യപ്പെടുത്തരുത്\' വഴി അറിയിപ്പുകൾ താൽക്കാലികമായി നിർത്തി"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ഇപ്പോൾ ആരംഭിക്കുക"</string>
<string name="empty_shade_text" msgid="708135716272867002">"അറിയിപ്പുകൾ ഒന്നുമില്ല"</string>
@@ -527,6 +533,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"സ്ക്രീൻ പിൻ ചെയ്തു"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'തിരികെ\', \'ചുരുക്കവിവരണം\' എന്നിവ സ്പർശിച്ച് പിടിക്കുക."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'തിരികെ പോവുക\', \'ഹോം\' ബട്ടണുകൾ സ്പർശിച്ച് പിടിക്കുക."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്ത് പിടിക്കുക."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'ചുരുക്കവിവരണം\' സ്പർശിച്ച് പിടിക്കുക."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'ഹോം\' ബട്ടൺ സ്പർശിച്ച് പിടിക്കുക."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"ഈ സ്ക്രീൻ അൺപിൻ ചെയ്യാൻ, \'തിരികെ പോവുക\', \'അവലോകനം\' ബട്ടണുകൾ സ്പർശിച്ച് പിടിക്കുക"</string>
@@ -638,14 +645,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"ഈ ആപ്പിൽ നിന്നുള്ള അറിയിപ്പുകൾ തുടർന്നും കാണിക്കണോ?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"സൗമ്യമായ"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"മുൻഗണനയുള്ള"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"എപ്പോഴും നിശബ്ദം. പുൾ ഡൗൺ ഷെയ്ഡിൽ പ്രദർശിപ്പിക്കുന്നു."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"എപ്പോഴും നിശബ്ദം. പുൾ ഡൗൺ ഷെയ്ഡിലും സ്റ്റാറ്റസ് ബാറിലും പ്രദർശിപ്പിക്കുന്നു."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"എപ്പോഴും നിശബ്ദം. പുൾ ഡൗൺ ഷെയ്ഡിലും ലോക്ക് സ്ക്രീനിലും പ്രദർശിപ്പിക്കുന്നു."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"എപ്പോഴും നിശബ്ദം. പുൾ ഡൗൺ ഷെയ്ഡിലും സ്റ്റാറ്റസ് ബാറിലും ലോക്ക് സ്ക്രീനിലും പ്രദർശിപ്പിക്കുന്നു."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"ശബ്ദം ഉണ്ടാക്കുകയും, പുൾ ഡൗൺ ഷെയ്ഡിലും സ്റ്റാറ്റസ് ബാറിലും ലോക്ക് സ്ക്രീനിലും പ്രദർശിപ്പിക്കുകയും ചെയ്യുന്നു."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"പുൾ ഡൗൺ ഷെയ്ഡിൽ മാത്രമുള്ള അറിയിപ്പുകളിൽ ശ്രദ്ധ കേന്ദ്രീകരിക്കാൻ നിങ്ങളെ സഹായിക്കുന്നു. എപ്പോഴും നിശബ്ദം."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"കുറഞ്ഞ പ്രാധാന്യമുള്ള മുൻഗണനാ അറിയിപ്പുകൾ പ്രദർശിപ്പിക്കുന്നു. എപ്പോഴും നിശബ്ദം."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"കുറഞ്ഞ പ്രാധാന്യമുള്ള മുൻഗണനാ അറിയിപ്പുകൾ പ്രദർശിപ്പിക്കുന്നു. എപ്പോഴും നിശബ്ദം."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"കുറഞ്ഞ പ്രാധാന്യമുള്ള മുൻഗണനാ അറിയിപ്പുകൾ പ്രദർശിപ്പിക്കുന്നു. എപ്പോഴും നിശബ്ദം."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ശബ്ദവും സ്റ്റാറ്റസ് ബാർ ഐക്കണും ഉപയോഗിച്ച് നിങ്ങളുടെ ശ്രദ്ധ അതിലേക്ക് നൽകുക. ലോക്ക് സ്ക്രീനിൽ കാണിക്കുന്നു."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"ഈ അറിയിപ്പുകൾ പരിഷ്ക്കരിക്കാനാവില്ല."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"അറിയിപ്പുകളുടെ ഈ ഗ്രൂപ്പ് ഇവിടെ കോണ്ഫിഗര് ചെയ്യാൻ കഴിയില്ല"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"പ്രോക്സി അറിയിപ്പ്"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"ഈ ആപ്പ് ക്യാമറ ഉപയോഗിക്കുന്നുണ്ട്."</string>
<string name="appops_microphone" msgid="741508267659494555">"ഈ ആപ്പ് മൈക്രോഫോൺ ഉപയോഗിക്കുന്നു."</string>
@@ -712,7 +722,7 @@
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"പുതിയവ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"മടങ്ങുക"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"അറിയിപ്പുകൾ"</string>
- <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"കീബോഡ് കുറുക്കുവഴികൾ"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"കീബോർഡ് കുറുക്കുവഴികൾ"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="8413348767825486492">"കീബോർഡ് ലേഔട്ട് മാറുക"</string>
<string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"അപ്ലിക്കേഷനുകൾ"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"അസിസ്റ്റ്"</string>
@@ -880,7 +890,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"ആപ്പുകൾ പശ്ചാത്തലത്തിൽ റൺ ചെയ്യുന്നു"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"ബാറ്ററി, ഡാറ്റ ഉപയോഗം എന്നിവയുടെ വിശദാംശങ്ങളറിയാൻ ടാപ്പുചെയ്യുക"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"മൊബൈൽ ഡാറ്റ ഓഫാക്കണോ?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"നിങ്ങൾക്ക് ഡാറ്റയിലേക്കുള്ള ആക്സസ് ഇല്ല അല്ലെങ്കിൽ <xliff:g id="CARRIER">%s</xliff:g> മുഖേനയുള്ള ഇന്റർനെറ്റില്ല. വൈഫൈ മുഖേനയുള്ള ഇന്റർനെറ്റ് മാത്രമേ ഉണ്ടായിരിക്കൂ."</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"നിങ്ങൾക്ക് ഡാറ്റയിലേക്ക് ആക്സസോ അല്ലെങ്കിൽ <xliff:g id="CARRIER">%s</xliff:g> മുഖേനയുള്ള ഇന്റർനെറ്റോ ഉണ്ടാകില്ല. വൈഫൈ മുഖേന മാത്രമായിരിക്കും ഇന്റർനെറ്റ് ലഭ്യത."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"നിങ്ങളുടെ കാരിയർ"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"അനുമതി അഭ്യർത്ഥനയെ ഒരു ആപ്പ് മറയ്ക്കുന്നതിനാൽ, ക്രമീകരണത്തിന് നിങ്ങളുടെ പ്രതികരണം പരിശോധിച്ചുറപ്പിക്കാനാകില്ല."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_2">%2$s</xliff:g> സ്ലൈസുകൾ കാണിക്കാൻ <xliff:g id="APP_0">%1$s</xliff:g>-നെ അനുവദിക്കണോ?"</string>
@@ -911,6 +921,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> തുറക്കുക"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനുള്ള ബബിളുകളുടെ ക്രമീകരണം"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ൽ നിന്നും ബബിളുകളെ അനുവദിക്കണോ?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"മാനേജ് ചെയ്യുക"</string>
<string name="no_bubbles" msgid="337101288173078247">"നിരസിക്കുക"</string>
<string name="yes_bubbles" msgid="668809525728633841">"അനുവദിക്കുക"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"എന്നോട് പിന്നീട് ചോദിക്കുക"</string>
@@ -921,4 +932,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"മുകളിൽ വലതുഭാഗത്തേക്ക് നീക്കുക"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"ചുവടെ ഇടതുഭാഗത്തേക്ക് നീക്കുക"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"ചുവടെ വലതുഭാഗത്തേക്ക് നീക്കുക"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 5377a59..af58d4b 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>-д"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> хүртэл"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Бараан загвар"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC-г цуцалсан"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC-г идэвхжүүлсэн"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Дахиж үл харуулах"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Бүгдийг арилгах"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Удирдах"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Эелдэг мэдэгдэл"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Бүх эелдэг мэдэгдлийг устгах"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Бүү саад бол горимын түр зогсоосон мэдэгдэл"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Одоо эхлүүлэх"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Мэдэгдэл байхгүй"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Дэлгэц эхэнд байрлуулагдсан"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Таныг тогтоосныг болиулах хүртэл үүнийг харуулна. Тогтоосныг болиулахын тулд Буцах, Тоймыг дараад хүлээнэ үү."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Таныг тогтоосныг болиулах хүртэл үүнийг харуулсан хэвээр байна. Тогтоосныг болиулахын тулд Буцах, Нүүр хуудас товчлуурыг дараад хүлээнэ үү."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Та тогтоосныг болиулах хүртэл үүнийг харуулсан хэвээр байна. Тогтоосныг болиулахын тулд дээш удаан шударна уу."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Таныг тогтоосныг болиулах хүртэл харагдах болно. Тогтоосныг болиулахын тулд Буцах товчлуурыг дараад, хүлээнэ үү."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Таныг тогтоосныг болиулах хүртэл үүнийг харуулсан хэвээр байна. Тогтоосныг болиулахын тулд Нүүр хуудас товчлуурыг дараад хүлээнэ үү."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Энэ дэлгэцийг тогтоосныг болиулахын тулд Буцах, Тойм товчлуурыг дараад хүлээнэ үү"</string>
@@ -637,15 +642,18 @@
<string name="inline_turn_off_notifications" msgid="8635596135532202355">"Мэдэгдлийг унтраах"</string>
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Энэ аппаас мэдэгдэл харуулсан хэвээр байх уу?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Бага ач холбогдолтой"</string>
- <string name="notification_alert_title" msgid="3966526305405016221">"Дунд зэргийн ач холбогдолтой"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Тогтмол чимээгүй байна. Доош татдаг сүүдэрт харагдана."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Тогтмол чимээгүй байна. Доош татдаг сүүдэр болон статусын хэсэгт харагдана."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Тогтмол чимээгүй байна. Доош татдаг сүүдэр болон түгжигдсэн дэлгэцэд харагдана."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Тогтмол чимээгүй байна. Доош татдаг сүүдэр, статусын хэсэг болон түгжигдсэн дэлгэцэд харагдана."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Дуугарах бөгөөд доош татдаг сүүдэр, статусын хэсэг болон түгжигдсэн дэлгэцэд харагдана."</string>
+ <string name="notification_alert_title" msgid="3966526305405016221">"Чухал ач холбогдолтой"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Танд зөвхөн доош татдаг сүүдрийн мэдэгдлээр төвлөрөхөд тусалдаг. Үргэлж чимээгүй байна."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Доорх ач холбогдолтой мэдэгдлийг харуулдаг. Үргэлж чимээгүй байна."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Доорх ач холбогдолтой мэдэгдлийг харуулдаг. Үргэлж чимээгүй байна."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Доорх ач холбогдолтой мэдэгдлийг харуулдаг. Үргэлж чимээгүй байна."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Таны анхаарлыг дуу болон статус самбарын дүрс тэмдгээр татдаг. Түгжигдсэн дэлгэц дээр харуулдаг."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Эдгээр мэдэгдлийг өөрчлөх боломжгүй."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Энэ бүлэг мэдэгдлийг энд тохируулах боломжгүй байна"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Прокси хийсэн мэдэгдэл"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Энэ апп камерыг ашиглаж байна."</string>
<string name="appops_microphone" msgid="741508267659494555">"Энэ апп микрофоныг ашиглаж байна."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g>-г нээх"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н хөөсний тохиргоо"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н хөөсийг зөвшөөрөх үү?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Удирдах"</string>
<string name="no_bubbles" msgid="337101288173078247">"Татгалзах"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Зөвшөөрөх"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Надаас дараа асуу"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Баруун дээш зөөх"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Зүүн доош зөөх"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Баруун доош зөөх"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 0a8d008..ad56eb6 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -275,8 +275,8 @@
<string name="accessibility_clear_all" msgid="5235938559247164925">"सर्व सूचना साफ करा."</string>
<string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
- <item quantity="one">आत आणखी <xliff:g id="NUMBER_1">%s</xliff:g> सूचना.</item>
<item quantity="other">आत आणखी <xliff:g id="NUMBER_1">%s</xliff:g> सूचना.</item>
+ <item quantity="one">आत आणखी <xliff:g id="NUMBER_0">%s</xliff:g> सूचना.</item>
</plurals>
<string name="notification_summary_message_format" msgid="715071952312553396">"<xliff:g id="CONTACT_NAME">%1$s</xliff:g>: <xliff:g id="MESSAGE_CONTENT">%2$s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"सूचना सेटिंग्ज"</string>
@@ -338,7 +338,7 @@
<string name="quick_settings_cast_no_wifi" msgid="2696477881905521882">"वाय-फाय कनेक्ट केलेले नाही"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"चमक"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"स्वयंचलित"</string>
- <string name="quick_settings_inversion_label" msgid="8790919884718619648">"रंगांचा क्रम उलटा लावा"</string>
+ <string name="quick_settings_inversion_label" msgid="8790919884718619648">"रंग उलटे लावा"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"रंग सुधारणा मोड"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"अधिक सेटिंग्ज"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"पूर्ण झाले"</string>
@@ -350,8 +350,8 @@
<string name="quick_settings_hotspot_secondary_label_transient" msgid="8010579363691405477">"सुरू करत आहे…"</string>
<string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="5672131949987422420">"डेटा सेव्हर सुरू आहे"</string>
<plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="2324635800672199428">
- <item quantity="one">%d डिव्हाइस</item>
<item quantity="other">%d डिव्हाइस</item>
+ <item quantity="one">%d डिव्हाइस</item>
</plurals>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"सूचना"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"फ्लॅशलाइट"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> वाजता चालू"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> पर्यंत"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"गडद थीम"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC अक्षम केले आहे"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC सक्षम केले आहे"</string>
@@ -434,8 +436,8 @@
<string name="user_add_user_message_short" msgid="2161624834066214559">"तुम्ही एक नवीन वापरकर्ता जोडता तेव्हा, त्या व्यक्तीने त्यांचे स्थान सेट करणे आवश्यक असते.\n\nकोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अॅप्स अपडेट करू शकतो."</string>
<string name="user_limit_reached_title" msgid="7374910700117359177">"वापरकर्ता मर्यादा गाठली"</string>
<plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
- <item quantity="one">तुम्ही <xliff:g id="COUNT">%d</xliff:g> वापरकर्त्यापर्यंत जोडू शकता.</item>
<item quantity="other">तुम्ही <xliff:g id="COUNT">%d</xliff:g> वापरकर्त्यांपर्यंत जोडू शकता.</item>
+ <item quantity="one">फक्त एक वापरकर्ता तयार केला जाऊ शकतो.</item>
</plurals>
<string name="user_remove_user_title" msgid="4681256956076895559">"वापरकर्त्यास काढायचे?"</string>
<string name="user_remove_user_message" msgid="1453218013959498039">"या वापरकर्त्याचे सर्व अॅप्स आणि डेटा काढून टाकला जाईल."</string>
@@ -448,6 +450,10 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"पुन्हा दर्शवू नका"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"सर्व साफ करा"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"व्यवस्थापित करा"</string>
+ <!-- no translation found for notification_section_header_gentle (8356064473678167305) -->
+ <skip />
+ <!-- no translation found for accessibility_notification_section_header_gentle_clear_all (4270384919249494640) -->
+ <skip />
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"व्यत्यय आणून नकाद्वारे सूचना थांबवल्या"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"आता सुरू करा"</string>
<string name="empty_shade_text" msgid="708135716272867002">"सूचना नाहीत"</string>
@@ -527,6 +533,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"स्क्रीन पिन केलेली आहे"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"तुम्ही अनपिन करेर्यंत हे यास दृश्यामध्ये ठेवते. अनपिन करण्यासाठी परत आणि विहंगावलोकनास स्पर्श करा आणि धरून ठेवा."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"तुम्ही अनपिन करेर्यंत हे त्याला दृश्यामध्ये ठेवते. अनपिन करण्यासाठी मागे आणि होम वर स्पर्श करा आणि धरून ठेवा."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"हे तुम्ही अनपिन करेपर्यंत दृश्यमान ठेवते. वरती स्वाइप करा आणि अनपिन करण्यासाठी धरून ठेवा."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"तुम्ही अनपिन करेर्यंत हे यास दृश्यामध्ये ठेवते. अनपिन करण्यासाठी विहंगावलोकनास स्पर्श करा आणि धरून ठेवा."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"तुम्ही अनपिन करेपर्यंत हे त्यास दृश्यामध्ये ठेवते. अनपिन करण्यासाठी होमला स्पर्श करा आणि धरून ठेवा."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"हा स्क्रीन अनपिन करण्यासाठी, मागे आणि अवलोकन बटणांना स्पर्श करून धरून ठेवा"</string>
@@ -638,14 +645,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"या अॅपकडील सूचना दाखवणे सुरू ठेवायचे?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"हळू आवाजातील"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"प्राधान्यकृत"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"नेहमी सायलंट. पूल-डाउन शेडमध्ये प्रदर्शित करते."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"नेहमी सायलंट. पूल-डाउन शेड आणि स्टेटस बारमध्ये प्रदर्शित करते."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"नेहमी सायलंट. पूल-डाउन शेडमध्ये आणि लॉक स्क्रीनवर प्रदर्शित करते."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"नेहमी सायलंट. पूल-डाउन शेडमध्ये, स्टेटस बारमध्ये आणि लॉक स्क्रीनवर प्रदर्शित करते."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"आवाज करते आणि पूल-डाउन शेडमध्ये, स्टेटस बारमध्ये आणि लॉक स्क्रीनवर प्रदर्शित करते."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"फक्त पुल डाउन शेडमध्ये सूचनांवर लक्ष केंद्रीत करण्यात मदत करते. नेहमी सायलंट."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"कमी प्राधान्य असलेल्या सूचना दाखवते. नेहमी सायलंट."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"कमी प्राधान्य असलेल्या सूचना दाखवते. नेहमी सायलंट."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"कमी प्राधान्य असलेल्या सूचना दाखवते. नेहमी सायलंट."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"आवाज आणि स्टेटस बार आयकनसह तुमचे लक्ष वेधून घेते. लॉक स्क्रीनवर दाखवते."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"या सूचनांमध्ये सुधारणा केली जाऊ शकत नाही."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"या सूचनांचा संच येथे कॉन्फिगर केला जाऊ शकत नाही"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"प्रॉक्सी केलेल्या सूचना"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"हे अॅप कॅमेरा वापरत आहे."</string>
<string name="appops_microphone" msgid="741508267659494555">"हे अॅप मायक्रोफोन वापरत आहे."</string>
@@ -670,12 +680,12 @@
<string name="snooze_undo" msgid="6074877317002985129">"पूर्ववत करा"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> साठी स्नूझ करा"</string>
<plurals name="snoozeHourOptions" formatted="false" msgid="2124335842674413030">
- <item quantity="one"> %d तास</item>
<item quantity="other"> %d तास</item>
+ <item quantity="one">%d तास</item>
</plurals>
<plurals name="snoozeMinuteOptions" formatted="false" msgid="4127251700591510196">
- <item quantity="one"> %d मिनिट</item>
<item quantity="other"> %d मिनिटे</item>
+ <item quantity="one">%d मिनिट</item>
</plurals>
<string name="battery_panel_title" msgid="7944156115535366613">"बॅटरी वापर"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"चार्ज करताना बॅटरी बचतकर्ता उपलब्ध नाही"</string>
@@ -733,9 +743,9 @@
<string name="accessibility_long_click_tile" msgid="6687350750091842525">"सेटिंग्ज उघडा"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"हेडफोन कनेक्ट केले"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"हेडसेट कनेक्ट केला"</string>
- <string name="data_saver" msgid="5037565123367048522">"डेटा बचतकर्ता"</string>
- <string name="accessibility_data_saver_on" msgid="8454111686783887148">"डेटा बचतकर्ता चालू आहे"</string>
- <string name="accessibility_data_saver_off" msgid="8841582529453005337">"डेटा बचतकर्ता बंद आहे"</string>
+ <string name="data_saver" msgid="5037565123367048522">"डेटा सेव्हर"</string>
+ <string name="accessibility_data_saver_on" msgid="8454111686783887148">"डेटा सेव्हर चालू आहे"</string>
+ <string name="accessibility_data_saver_off" msgid="8841582529453005337">"डेटा सेव्हर बंद आहे"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"चालू"</string>
<string name="switch_bar_off" msgid="8803270596930432874">"बंद"</string>
<string name="nav_bar" msgid="1993221402773877607">"नॅव्हिगेशन बार"</string>
@@ -911,6 +921,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> उघडा"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> बबलसाठी सेटिंग्ज"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> वरील बबलना अनुमती द्यायची?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"व्यवस्थापित करा"</string>
<string name="no_bubbles" msgid="337101288173078247">"नाकारा"</string>
<string name="yes_bubbles" msgid="668809525728633841">"अनुमती द्या"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"मला नंतर विचारा"</string>
@@ -921,4 +932,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"वर उजवीकडे हलवा"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"तळाशी डावीकडे हलवा"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"तळाशी उजवीकडे हलवा"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index d75c97f..93b4fcc 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Dihidupkan pada <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Hingga <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema Gelap"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC dilumpuhkan"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC didayakan"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Jangan tunjukkan lagi"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Kosongkan semua"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Urus"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Pemberitahuan lembut"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Kosongkan semua pemberitahuan lembut"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Pemberitahuan dijeda oleh Jangan Ganggu"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Mulakan sekarang"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Tiada pemberitahuan"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Skrin telah disemat"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Tindakan ini memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh & tahan Kembali dan Ikhtisar untuk menyahsemat."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Tindakan ini memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh & tahan Kembali dan Skrin Utama untuk menyahsemat."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Tindakan ini memastikan skrin kelihatan sehingga anda menyahsemat. Leret ke atas & tahan untuk menyahsemat."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Tindakan ini memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh & tahan Ikhtisar untuk menyahsemat."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Tindakan ini memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh & tahan Skrin Utama untuk menyahsemat."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Untuk menyahsemat skrin ini, sentuh & tahan butang Kembali dan Ikhtisar"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Terus tunjukkan pemberitahuan daripada apl ini?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Lembut"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Diutamakan"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Sentiasa senyap. Dipaparkan dalam bidai tarik turun."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Sentiasa senyap. Dipaparkan dalam bidai tarik turun & bar status."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Sentiasa senyap. Dipaparkan dalam bidai tarik turun & pada skrin kunci."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Sentiasa senyap. Dipaparkan dalam bidai tarik turun, bar status & pada skrin kunci."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Berbunyi dan dipaparkan dalam bidai tarik turun, bar status & pada skrin kunci."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Membantu anda fokus dengan memaparkan pemberitahuan sahaja dalam bidai tarik turun. Sentiasa senyap."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Dipaparkan di bawah pemberitahuan keutamaan. Sentiasa senyap."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Dipaparkan di bawah pemberitahuan keutamaan. Sentiasa senyap."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Dipaparkan di bawah pemberitahuan keutamaan. Sentiasa senyap."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Menarik perhatian anda dengan bunyi & ikon bar status. Ditunjukkan pada skrin kunci."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Pemberitahuan ini tidak boleh diubah suai."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Kumpulan pemberitahuan ini tidak boleh dikonfigurasikan di sini"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Pemberitahuan berproksi"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Apl ini sedang menggunakan kamera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Apl ini sedang menggunakan mikrofon."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Buka <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Tetapan untuk gelembung <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Benarkan gelembung daripada <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Urus"</string>
<string name="no_bubbles" msgid="337101288173078247">"Tolak"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Benarkan"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Tanya saya kemudian"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Alihkan ke atas sebelah kanan"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Alihkan ke bawah sebelah kiri"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Alihkan ke bawah sebelah kanan"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 22b2c12..f058f92 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> တွင် ဖွင့်ရန်"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> အထိ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"မှောင်သည့် အပြင်အဆင်"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ကို ပိတ်ထားသည်"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ကို ဖွင့်ထားသည်"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"နောက်ထပ် မပြပါနှင့်"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"အားလုံး ဖယ်ရှားရန်"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"စီမံရန်"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"မသိမသာ အကြောင်းကြားချက်များ"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"မသိမသာ အကြောင်းကြားချက်အားလုံး ရှင်းပါ"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"အကြောင်းကြားချက်များကို \'မနှောင့်ယှက်ရ\' က ခေတ္တရပ်ထားသည်"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ယခု စတင်ပါ"</string>
<string name="empty_shade_text" msgid="708135716272867002">"အကြောင်းကြားချက်များ မရှိ"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"မျက်နှာပြင် ပင်ထိုးပြီးပါပြီ"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"သင်ပင်မဖြုတ်မခြင်း ၎င်းကို ပြသထားပါမည်။ ပင်ဖြုတ်ရန် Back နှင့် Overview ကို ထိ၍ဖိထားပါ။"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"သင်က ပင်မဖြုတ်မခြင်း ၎င်းကို ပြသထားပါမည်။ ပင်ဖြုတ်ရန် \'နောက်သို့\' နှင့် \'ပင်မ\' ခလုတ်တို့ကို တို့၍ဖိထားပါ။"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"သင်က ပင်မဖြုတ်မချင်း ၎င်းကို ပြသထားပါမည်။ ပင်ဖြုတ်ရန် အပေါ်သို့ပွတ်ဆွဲပြီး ဖိထားပါ။"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"သင်ပင်မဖြုတ်မချင်း ၎င်းကိုပြသထားပါမည်။ ပင်ဖြုတ်ရန် Overview ကိုထိပြီး ဖိထားပါ။"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"သင်က ပင်မဖြုတ်မချင်း ၎င်းကိုပြသထားပါမည်။ ပင်ဖြုတ်ရန် \'ပင်မ\' ခလုတ်ကို တို့၍ဖိထားပါ။"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"ဤမျက်နှာပြင်ကို ပင်ဖြုတ်ရန်အတွက် \'နောက်သို့\' နှင့် \'အနှစ်ချုပ်\' ခလုတ်တို့ကို တို့၍ဖိထားပါ"</string>
@@ -636,16 +641,19 @@
<string name="inline_silent_button_keep_alerting" msgid="327696842264359693">"ဆက်လက် သတိပေးရန်"</string>
<string name="inline_turn_off_notifications" msgid="8635596135532202355">"အကြောင်းကြားချက်များ ပိတ်ရန်"</string>
<string name="inline_keep_showing_app" msgid="1723113469580031041">"ဤအက်ပ်ထံမှ အကြောင်းကြားချက်များကို ဆက်ပြလိုပါသလား။"</string>
- <string name="notification_silence_title" msgid="7352089096356977930">"ညင်သာသည်"</string>
+ <string name="notification_silence_title" msgid="7352089096356977930">"မသိမသာ"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"ဦးစားပေး"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"အမြဲ အသံတိတ်ပါ။ ဆွဲချသည့်အရိပ်တွင် ပြသပါ။"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"အမြဲ အသံတိတ်ပါ။ ဆွဲချသည့်အရိပ်နှင့် အခြေအနေပြနေရာတွင် ပြသပါ။"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"အမြဲ အသံတိတ်ပါ။ ဆွဲချသည့်အရိပ်နှင့် လော့ခ်ချထားချိန် မျက်နှာပြင်တွင် ပြသပါ။"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"အမြဲ အသံတိတ်ပါ။ ဆွဲချသည့်အရိပ်၊ အခြေအနေပြနေရာနှင့် လော့ခ်ချထားချိန် မျက်နှာပြင်တွင် ပြသပါ။"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"အသံပြုပြီး ဆွဲချသည့်အရိပ်၊ အခြေအနေပြနေရာနှင့် လော့ခ်ချထားချိန် မျက်နှာပြင်တွင် ပြသပါ။"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"အပေါ်မှဆွဲချသည့် နေရာတွင်သာ အကြောင်းကြားချက်များကို အာရုံစိုက်ရန် အထောက်ကူပြုပေးသည်။ အမြဲ အသံတိတ်ရန်။"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"ဦးစားပေးအကြောင်းကြားချက်များ၏ အောက်တွင်ဖော်ပြသည်။ အမြဲ အသံတိတ်ရန်။"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"ဦးစားပေးအကြောင်းကြားချက်များ၏ အောက်တွင်ဖော်ပြသည်။ အမြဲ အသံတိတ်ရန်။"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"ဦးစားပေးအကြောင်းကြားချက်များ၏ အောက်တွင်ဖော်ပြသည်။ အမြဲ အသံတိတ်ရန်။"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"အသံအပါအဝင် အခြေနေပြနေရာ သင်္ကေတဖြင့် သင်သတိထားမိအောင် ပြုလုပ်သည်။ လော့ခ်ချထားချိန် မျက်နှာပြင်တွင် ပြရန်။"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"ဤအကြောင်းကြားချက်များကို ပြုပြင်၍ မရပါ။"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"ဤအကြောင်းကြားချက်အုပ်စုကို ဤနေရာတွင် စီစဉ်သတ်မှတ်၍ မရပါ"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"ပရောက်စီထည့်ထားသော အကြောင်းကြားချက်"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"ဤအက်ပ်က ကင်မရာကို အသုံးပြုနေသည်။"</string>
<string name="appops_microphone" msgid="741508267659494555">"ဤအက်ပ်က မိုက်ခရိုဖုန်းကို အသုံးပြုနေသည်။"</string>
@@ -880,7 +888,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"နောက်ခံတွင် ပွင့်နေသော အက်ပ်များ"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"ဘက်ထရီနှင့် ဒေတာအသုံးပြုမှု အသေးစိတ်ကို ကြည့်ရန် တို့ပါ"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"မိုဘိုင်းဒေတာ ပိတ်လိုပါသလား။"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"<xliff:g id="CARRIER">%s</xliff:g> မှ ဒေတာ သို့မဟုတ် အင်တာနက်ကို သုံးစွဲ၍ မရနိုင်ပါ။ Wi-Fi အသုံးပြု၍သာ အင်တာနက် သုံးစွဲနိုင်ပါသည်။"</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"<xliff:g id="CARRIER">%s</xliff:g> မှတစ်ဆင့် ဒေတာ သို့မဟုတ် အင်တာနက်ကို သုံးစွဲ၍ မရနိုင်ပါ။ Wi-Fi အသုံးပြု၍သာ အင်တာနက် သုံးစွဲနိုင်ပါသည်။"</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"သင်၏ ဝန်ဆောင်မှုပေးသူ"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"အပလီကေးရှင်းတစ်ခုက ခွင့်ပြုချက်တောင်းခံမှုကို ပိတ်ထားသောကြောင့် ဆက်တင်များသည် သင်၏ လုပ်ဆောင်ကို တုံ့ပြန်နိုင်ခြင်းမရှိပါ။"</string>
<string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> အား <xliff:g id="APP_2">%2$s</xliff:g> ၏အချပ်များ ပြသခွင့်ပြုပါသလား။"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကိုဖွင့်ရန်"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> ပူဖောင်းကွက်များအတွက် ဆက်တင်များ"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> မှ ပူဖောင်းကွက်များကို ခွင့်ပြုလိုပါသလား။"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"စီမံရန်"</string>
<string name="no_bubbles" msgid="337101288173078247">"ငြင်းပယ်ရန်"</string>
<string name="yes_bubbles" msgid="668809525728633841">"ခွင့်ပြုရန်"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"နောက်မှ မေးရန်"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"ညာဘက်ထိပ်သို့ ရွှေ့ပါ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"ဘယ်အောက်ခြေသို့ ရွှေ့ရန်"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"ညာအောက်ခြေသို့ ရွှေ့ပါ"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 6faded5b..aaff2fa 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"På kl. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Til <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Mørkt tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC er slått av"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC er slått på"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ikke vis igjen"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Fjern alt"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Administrer"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Diskré varsler"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Fjern alle diskré varsler"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Varsler er satt på pause av «Ikke forstyrr»"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Start nå"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Ingen varsler"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Skjermen er låst"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"På denne måten blir skjermen synlig frem til du løsner den. Trykk og hold inne Tilbake og Oversikt for å løsne den."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"På denne måten blir skjermen synlig frem til du løsner den. Trykk og hold inne Tilbake og Startside for å løsne den."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"På denne måten blir skjermen synlig frem til du løsner den. Sveip opp og hold for å løsne."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"På denne måten blir skjermen synlig frem til du løsner den. Trykk og hold inne Oversikt for å løsne den."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"På denne måten blir skjermen synlig frem til du løsner den. Trykk og hold inne Startside for å løsne den."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"For å løsne denne skjermen, trykk på og hold inne Tilbake- og Oversikt-knappene"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Vil du fortsette å vise varsler fra denne appen?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Diskré"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritert"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Alltid lydløs. Vises i nedtrekkspanelet."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Alltid lydløs. Vises i nedtrekkspanelet og statusfeltet."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Alltid lydløs. Vises i nedtrekkspanelet og på låseskjermen."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Alltid lydløs. Vises i nedtrekkspanelet, statusfeltet og på låseskjermen."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Lager lyd og vises i nedtrekkspanelet, statusfeltet og på låseskjermen."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Hjelper deg med å fokusere, med varsler bare i nedtrekkspanelet. Alltid lydløs."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Vises under prioritetsvarsler. Alltid lydløs."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Vises under prioritetsvarsler. Alltid lydløs."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Vises under prioritetsvarsler. Alltid lydløs."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Får oppmerksomheten din med lyd og et ikon i statusfeltet. Vises på låseskjermen."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Disse varslene kan ikke endres."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Denne varselgruppen kan ikke konfigureres her"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Omdirigert varsel"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Denne appen bruker kameraet."</string>
<string name="appops_microphone" msgid="741508267659494555">"Denne appen bruker mikrofonen."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Åpne <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Innstillinger for <xliff:g id="APP_NAME">%1$s</xliff:g>-bobler"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Vil du tillate bobler fra <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Administrer"</string>
<string name="no_bubbles" msgid="337101288173078247">"Avvis"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Tillat"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Spør meg senere"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Flytt til øverst til høyre"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Flytt til nederst til venstre"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Flytt til nederst til høyre"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index faa917b..5807b9d 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> मा सक्रिय"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> सम्म"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"अँध्यारो विषयवस्तु"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC लाई असक्षम पारिएको छ"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC लाई सक्षम पारिएको छ"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"फेरि नदेखाउनुहोस्"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"सबै हटाउनुहोस्"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"व्यवस्थित गर्नुहोस्"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"सामान्य सूचनाहरू"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"सबै सामान्य सूचनाहरू खाली गर्नुहोस्"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"बाधा नपुऱ्याउनुहोस् नामक मोडमार्फत पज पारिएका सूचनाहरू"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"अहिले सुरु गर्नुहोस्"</string>
<string name="empty_shade_text" msgid="708135716272867002">"कुनै सूचनाहरू छैनन्"</string>
@@ -478,8 +482,8 @@
<string name="disable_vpn" msgid="4435534311510272506">"VPN असक्षम गर्नुहोस्"</string>
<string name="disconnect_vpn" msgid="1324915059568548655">"विच्छेद VPN"</string>
<string name="monitoring_button_view_policies" msgid="100913612638514424">"नीतिहरू हेर्नुहोस्"</string>
- <string name="monitoring_description_named_management" msgid="5281789135578986303">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ले तपाईंको यन्त्रको व्यवस्थापन गर्छ।BREAK\n\nतपाईंका प्रशासकले सेटिङहरू, संस्थागत पहुँच, अनुप्रयोगहरू, तपाईंको यन्त्रसँग सम्बन्धित डेटा र तपाईंको यन्त्रको स्थान सम्बन्धी जानकारीको अनुगमन तथा व्यवस्थापन गर्न सक्नुहुन्छ।\n\nथप जानकारीका लागि आफ्नो प्रशासकलाई सम्पर्क गर्नुहोस्।"</string>
- <string name="monitoring_description_management" msgid="4573721970278370790">"तपाईंको संगठनले तपाईंको यन्त्रको व्यवस्थापन गर्छ।\n\nतपाईंका प्रशासकले सेटिङहरू, संस्थागत पहुँच, अनुप्रयोगहरू, तपाईंको यन्त्रसँग सम्बन्धित डेटा र तपाईंको यन्त्रको स्थान सम्बन्धी जानकारीको अनुगमन तथा व्यवस्थापन गर्न सक्नुहुन्छ।\n\nथप जानकारीका लागि आफ्नो प्रशासकलाई सम्पर्क गर्नुहोस्।"</string>
+ <string name="monitoring_description_named_management" msgid="5281789135578986303">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ले तपाईंको यन्त्रको व्यवस्थापन गर्छ।BREAK\n\nतपाईंका प्रशासकले सेटिङहरू, संस्थागत पहुँच, अनुप्रयोगहरू, तपाईंको यन्त्रसँग सम्बन्धित डेटा र तपाईंको यन्त्रको स्थानसम्बन्धी जानकारीको अनुगमन तथा व्यवस्थापन गर्न सक्नुहुन्छ।\n\nथप जानकारीका लागि आफ्नो प्रशासकलाई सम्पर्क गर्नुहोस्।"</string>
+ <string name="monitoring_description_management" msgid="4573721970278370790">"तपाईंको संगठनले तपाईंको यन्त्रको व्यवस्थापन गर्छ।\n\nतपाईंका प्रशासकले सेटिङहरू, संस्थागत पहुँच, अनुप्रयोगहरू, तपाईंको यन्त्रसँग सम्बन्धित डेटा र तपाईंको यन्त्रको स्थानसम्बन्धी जानकारीको अनुगमन तथा व्यवस्थापन गर्न सक्नुहुन्छ।\n\nथप जानकारीका लागि आफ्नो प्रशासकलाई सम्पर्क गर्नुहोस्।"</string>
<string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"तपाईंको संगठनले तपाईंको कार्य प्रोफाइलमा एउटा प्रमाणपत्र सम्बन्धी अख्तियार सुविधा स्थापित गऱ्यो। तपाईंको सुरक्षित नेटवर्क ट्राफिकको अनुगमन वा परिमार्जन हुनसक्छ।"</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"तपाईंको संगठनले तपाईंको कार्य प्रोफाइलमा एउटा प्रमाणपत्र सम्बन्धी अख्तियार सुविधा स्थापना गरेको छ। तपाईंको सुरक्षित नेटवर्क ट्राफिकको अनुगमन वा परिमार्जन हुनसक्छ।"</string>
<string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"यस यन्त्रमा एउटा प्रमाणपत्र सम्बन्धी अख्तियार सुविधा स्थापना गरिएको छ। तपाईंको सुरक्षित नेटवर्कको ट्राफिकको अनुगमन वा परिमार्जन हुनसक्छ।"</string>
@@ -490,7 +494,7 @@
<string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"तपाईंको व्यक्तिगत प्रोफाइल इमेल, अनुप्रयोग र वेबसाइटहरू लगायत तपाईंको नेटवर्कको गतिविधिको अनुगमन गर्नसक्ने <xliff:g id="VPN_APP">%1$s</xliff:g> मा जडान छ।"</string>
<string name="monitoring_description_do_header_generic" msgid="96588491028288691">"तपाईंको यन्त्र <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> द्वारा व्यवस्थापन गरिएको छ।"</string>
<string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ले तपाईंको यन्त्रको व्यवस्थापन गर्न <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> को प्रयोग गर्दछ।"</string>
- <string name="monitoring_description_do_body" msgid="3639594537660975895">"तपाईँको प्रशासकले सेटिङहरू, संस्थागत पहुँच, अनुप्रयोग, तपाईँको यन्त्रसँग सम्बन्धित डेटा र तपाईँको यन्त्रको स्थान सम्बन्धी जानकारीको अनुगमन तथा व्यवस्थापन गर्न सक्नुहुन्छ।"</string>
+ <string name="monitoring_description_do_body" msgid="3639594537660975895">"तपाईँको प्रशासकले सेटिङहरू, संस्थागत पहुँच, अनुप्रयोग, तपाईँको यन्त्रसँग सम्बन्धित डेटा र तपाईँको यन्त्रको स्थानसम्बन्धी जानकारीको अनुगमन तथा व्यवस्थापन गर्न सक्नुहुन्छ।"</string>
<string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
<string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"थप जान्नुहोस्"</string>
<string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"तपाईं <xliff:g id="VPN_APP">%1$s</xliff:g> मा जोडिनुभएको छ जसले इमेल, अनुप्रयोग र वेबसाइटहरू लगायत तपाईंको नेटवर्क सम्बन्धी गतिविधिको अनुगमन गर्न सक्छ।"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"पर्दा राखेका छ"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न पछाडि र परिदृश्य बटनलाई छोइराख्नुहोस्।"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न पछाडि र गृह नामक बटनहरूलाई छोइराख्नुहोस्।"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"तपाईंले अनपिन नगरेसम्म यस कार्यले यसलाई दृश्यमा राख्छ। अनपिन गर्न माथितिर स्वाइप गरी होल्ड गर्नुहोस्।"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न परिदृश्य बटनलाई छोइराख्नुहोस्।"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न गृह नामक बटनलाई छोइराख्नुहोस्।"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"यस स्क्रिनलाई अनपनि गर्न पछाडि र परिदृश्य नामक बटनहरूलाई छोइराख्नुहोस्"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"यो अनुप्रयोगका सूचनाहरू देखाउने क्रम जारी राख्ने हो?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"मौन"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"प्राथमिकता दिइएको"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"सधैँ मौन। पुल डाउन सेडमा देखिन्छ।"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"सधैँ मौन। पुल डाउन सेड र वस्तुस्थिति पट्टीमा देखिन्छ।"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"सधैँ मौन। पुल डाउन सेड र लक स्क्रिनमा देखिन्छ।"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"सधैँ मौन। पुल डाउन सेड, वस्तुस्थिति पट्टी र लक स्क्रिनमा देखिन्छ।"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"घन्टी बजाउँछ र पुल डाउन सेड, वस्तुस्थिति पट्टी र लक स्क्रिनमा देखिन्छ।"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"तपाईंलाई पुल डाउन सेडमा रहेका सूचनाहरूमा मात्र केन्द्रित हुन मद्दत गर्छ। सधैँ मौन।"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"न्यून प्राथमिकताका सूचनाहरू देखाउँछ। सधैँ मौन।"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"न्यून प्राथमिकताका सूचनाहरू देखाउँछ। सधैँ मौन।"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"न्यून प्राथमिकताका सूचनाहरू देखाउँछ। सधैँ मौन।"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ध्वनि र वस्तुस्थिति पट्टीको आइकनमार्फत तपाईंको ध्यान खिच्छ। लक स्क्रिनमा देखाउँछ।"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"यी सूचनाहरू परिमार्जन गर्न मिल्दैन।"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"यहाँबाट सूचनाहरूको यो समूह कन्फिगर गर्न सकिँदैन"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"प्रोक्सीमार्फत आउने सूचना"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"यो अनुप्रयोगले क्यामेराको प्रयोग गर्दै छ।"</string>
<string name="appops_microphone" msgid="741508267659494555">"यो अनुप्रयोगले माइक्रोफोनको प्रयोग गर्दै छ।"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> खोल्नुहोस्"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> का बबलसम्बन्धी सेटिङहरू"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> का बबलहरूलाई अनुमति दिने हो?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"व्यवस्थापन गर्नुहोस्"</string>
<string name="no_bubbles" msgid="337101288173078247">"अस्वीकार गर्नुहोस्"</string>
<string name="yes_bubbles" msgid="668809525728633841">"अनुमति दिनुहोस्"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"मलाई पछि सोध्नुहोस्"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"सिरानमा दायाँतिर सार्नुहोस्"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"पुछारमा बायाँतिर सार्नुहोस्"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"पुछारमा दायाँतिर सार्नुहोस्"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index f9bf47b..e25faa2 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -37,16 +37,20 @@
<color name="notification_ripple_untinted_color">#30ffffff</color>
<!-- The "inside" of a notification, reached via longpress -->
- <color name="notification_guts_bg_color">@*android:color/notification_material_background_color</color>
+ <color name="notification_guts_bg_color">@color/GM2_grey_900</color>
<!-- The color of the text inside a notification -->
<color name="notification_primary_text_color">@*android:color/notification_primary_text_color_dark</color>
- <color name="notification_guts_selection_bg">#202124</color>
- <color name="notification_guts_selection_border">#669DF6</color>
- <color name="notification_guts_link_icon_tint">@color/GM2_grey_200</color>
+ <color name="notification_guts_selection_bg">@color/GM2_grey_800</color>
+ <color name="notification_guts_selection_border">@color/GM2_grey_700</color>
+ <color name="notification_guts_link_icon_tint">@color/GM2_grey_500</color>
<color name="notification_guts_sub_text_color">@color/GM2_grey_200</color>
- <color name="notification_guts_header_text_color">@color/GM2_grey_100</color>
+ <color name="notification_guts_header_text_color">@color/GM2_grey_200</color>
+ <color name="notification_guts_button_color">@color/GM2_blue_200</color>
+
+ <color name="notification_section_header_label_color">@color/GM2_grey_200</color>
+ <color name="notification_channel_dialog_separator">@color/GM2_grey_700</color>
<!-- The color of the background in the top part of QSCustomizer -->
<color name="qs_customize_background">@color/GM2_grey_900</color>
@@ -65,4 +69,10 @@
<!-- The color of the text in the Global Actions menu -->
<color name="global_actions_alert_text">@color/GM2_red_300</color>
-</resources>
\ No newline at end of file
+
+ <!-- Biometric dialog colors -->
+ <color name="biometric_dialog_gray">#ff888888</color>
+ <color name="biometric_dialog_accent">#ff80cbc4</color> <!-- light teal -->
+ <color name="biometric_dialog_error">#fff28b82</color> <!-- red 300 -->
+
+</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index e506a93..2538f52 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -294,7 +294,7 @@
<string name="quick_settings_dnd_label" msgid="7112342227663678739">"Niet storen"</string>
<string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Alleen prioriteit"</string>
<string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Alleen wekkers"</string>
- <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"Totale stilte"</string>
+ <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"Helemaal stil"</string>
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> apparaten)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth uit"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Donker thema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is uitgeschakeld"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is ingeschakeld"</string>
@@ -397,8 +399,8 @@
<string name="phone_hint" msgid="4872890986869209950">"Vegen voor telefoon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Vegen vanaf pictogram voor spraakassistent"</string>
<string name="camera_hint" msgid="7939688436797157483">"Vegen voor camera"</string>
- <string name="interruption_level_none_with_warning" msgid="5114872171614161084">"Totale stilte. Hiermee worden schermlezers ook op stil gezet."</string>
- <string name="interruption_level_none" msgid="6000083681244492992">"Totale stilte"</string>
+ <string name="interruption_level_none_with_warning" msgid="5114872171614161084">"Helemaal stil. Hiermee worden schermlezers ook op stil gezet."</string>
+ <string name="interruption_level_none" msgid="6000083681244492992">"Helemaal stil"</string>
<string name="interruption_level_priority" msgid="6426766465363855505">"Alleen prioriteit"</string>
<string name="interruption_level_alarms" msgid="5226306993448328896">"Alleen wekkers"</string>
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Totale\nstilte"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Niet opnieuw weergeven"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Alles wissen"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Beheren"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Vriendelijke meldingen"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Alle vriendelijke meldingen wissen"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Meldingen onderbroken door \'Niet storen\'"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Nu starten"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Geen meldingen"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Scherm is vastgezet"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Het scherm blijft zichtbaar totdat je het losmaakt. Tik op Terug en Overzicht en houd deze vast om het scherm los te maken."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Het scherm blijft zichtbaar totdat je het losmaakt. Tik op Terug en Home en houd deze vast om het scherm los te maken."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Zo blijft het scherm zichtbaar totdat je dit losmaakt. Veeg omhoog en houd vast om los te maken."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Het scherm blijft zichtbaar totdat je het losmaakt. Tik op Overzicht en houd dit vast om het scherm los te maken."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Het scherm blijft zichtbaar totdat je het losmaakt. Tik op Home en houd dit vast om het scherm los te maken."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Tik op Terug en Overzicht en houd deze knoppen vast om dit scherm los te maken"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Meldingen van deze app blijven weergeven?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Vriendelijk"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Met prioriteit"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Altijd stil. Wordt weergegeven in pull-downvenster."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Altijd stil. Wordt weergegeven in pull-downvenster en statusbalk."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Altijd stil. Wordt weergegeven in pull-downvenster en op vergrendelingsscherm."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Altijd stil. Wordt weergegeven in pull-downvenster, statusbalk en op vergrendelingsscherm."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Maakt geluid en wordt weergegeven in pull-downvenster, statusbalk en op vergrendelingsscherm."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Helpt je focussen doordat meldingen alleen in het pull-downvenster worden weergegeven. Altijd stil."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Wordt weergegeven onder de prioriteitsmeldingen. Altijd stil."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Wordt weergegeven onder de prioriteitsmeldingen. Altijd stil."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Wordt weergegeven onder de prioriteitsmeldingen. Altijd stil."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Trekt de aandacht met geluid en een pictogram in de statusbalk. Wordt weergegeven op het vergrendelingsscherm."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Deze meldingen kunnen niet worden aangepast."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Deze groep meldingen kan hier niet worden geconfigureerd"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Melding via proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Deze app gebruikt de camera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Deze app gebruikt de microfoon."</string>
@@ -880,7 +888,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"Apps uitgevoerd op achtergrond"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tik voor batterij- en datagebruik"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"Mobiele data uitschakelen?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"Je hebt geen toegang tot gegevens of internet via <xliff:g id="CARRIER">%s</xliff:g>. Internet is alleen beschikbaar via wifi."</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"Je hebt geen toegang tot data of internet via <xliff:g id="CARRIER">%s</xliff:g>. Internet is alleen beschikbaar via wifi."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"je provider"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Aangezien een app een toestemmingsverzoek afdekt, kan Instellingen je reactie niet verifiëren."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> toestaan om segmenten van <xliff:g id="APP_2">%2$s</xliff:g> weer te geven?"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> openen"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Instellingen voor <xliff:g id="APP_NAME">%1$s</xliff:g>-ballonnen"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Ballonnen van <xliff:g id="APP_NAME">%1$s</xliff:g> toestaan?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Beheren"</string>
<string name="no_bubbles" msgid="337101288173078247">"Weigeren"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Toestaan"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Later vragen"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Naar rechtsboven verplaatsen"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Naar linksonder verplaatsen"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Naar rechtsonder verplaatsen"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 828827a..39714cf 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -324,7 +324,7 @@
<string name="quick_settings_user_title" msgid="4467690427642392403">"ୟୁଜର୍"</string>
<string name="quick_settings_user_new_user" msgid="9030521362023479778">"ନୂଆ ୟୁଜର୍"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"ୱାଇ-ଫାଇ"</string>
- <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"କନେକ୍ଟ ହୋଇନାହିଁ"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"ସଂଯୁକ୍ତ ହୋଇନାହିଁ"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ନେଟ୍ୱର୍କ ନାହିଁ"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"ୱାଇ-ଫାଇ ଅଫ୍"</string>
<string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"ୱାଇ-ଫାଇ ଅନ୍ ଅଛି"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>ରେ ଅନ୍ ହେବ"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> ପର୍ଯ୍ୟନ୍ତ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"ଗାଢ଼ା ଥିମ୍"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ସକ୍ଷମ କରାଯାଇଛି"</string>
@@ -448,6 +450,10 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"ପୁଣି ଦେଖାନ୍ତୁ ନାହିଁ"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"ସମସ୍ତ ଖାଲି କରନ୍ତୁ"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"ପରିଚାଳନା କରନ୍ତୁ"</string>
+ <!-- no translation found for notification_section_header_gentle (8356064473678167305) -->
+ <skip />
+ <!-- no translation found for accessibility_notification_section_header_gentle_clear_all (4270384919249494640) -->
+ <skip />
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ବିକଳ୍ପ ଦ୍ୱାରା ବିଜ୍ଞପ୍ତି ପଜ୍ ହୋଇଛି"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ବର୍ତ୍ତମାନ ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="empty_shade_text" msgid="708135716272867002">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string>
@@ -527,6 +533,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"ସ୍କ୍ରିନକୁ ପିନ୍ କରାଯାଇଛି"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"ଆପଣ ଅନପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍ କରିବାକୁ ସ୍ପର୍ଶ କରି ଧରିରଖନ୍ତୁ ଓ ଦେଖନ୍ତୁ।"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"ଆପଣ ଅନପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍ କରିବା ପାଇଁ ହୋମ୍ ଓ ବ୍ୟାକ୍ ବଟନ୍କୁ ଧରିରଖନ୍ତୁ।"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"ଆପଣ ଅନ୍ପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଯାଉଥିବ। ଅନ୍ପିନ୍ କରିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରି ଧରି ରଖନ୍ତୁ"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"ଆପଣ ଅନପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍ କରିବାକୁ ସ୍ପର୍ଶ କରନ୍ତୁ ଏବଂ ଓଭରଭ୍ୟୁକୁ ଧରିରଖନ୍ତୁ।"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"ଆପଣ ଅନପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍ କରିବା ପର୍ଯ୍ୟନ୍ତ ହୋମ୍କୁ ଦାବିଧରନ୍ତୁ।"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"ଏହି ସ୍କ୍ରୀନ୍କୁ ଅନପିନ୍ କରିବା ପାଇଁ, ବ୍ୟାକ୍ ଏବଂ ଓଭରଭ୍ୟୁ ବଟନ୍କୁ ଦାବିଧରନ୍ତୁ"</string>
@@ -638,14 +645,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"ଏହି ଆପ୍ରୁ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଦେଖାଇବା ଜାରି ରଖିବେ?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"ଧିରେ"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"ପ୍ରାଥମିକତା ଭିତ୍ତିକ"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"ସର୍ବଦା ନିରବ। ପୁଲ୍-ଡାଉନ୍ ସେଡ୍ରେ ପ୍ରଦର୍ଶିତ କରିଥାଏ।"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"ସର୍ବଦା ନିରବ। ପୁଲ୍-ଡାଉନ୍ ସେଡ୍ ଏବଂ ସ୍ଥିତି ବାର୍ରେ ପ୍ରଦର୍ଶନ କରିଥାଏ।"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"ସର୍ବଦା ନିରବ। ପୁଲ୍-ଡାଉନ୍ ସେଡ୍ ଏବଂ ଲକ୍ ସ୍କ୍ରିନ୍ରେ ପ୍ରଦର୍ଶିତ କରିଥାଏ।"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"ସର୍ବଦା ନିରବ। ପୁଲ୍-ଡାଉନ୍ ସେଡ୍, ସ୍ଥିତି ବାର୍ ଏବଂ ଲକ୍ ସ୍କ୍ରିନ୍ରେ ପ୍ରଦର୍ଶନ କରିଥାଏ।"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"ଶବ୍ଦ କରେ ଏବଂ ପୁଲ୍-ଡାଉନ୍ ସେଡ୍ ସ୍ଥିତି ବାର ଏବଂ ଲକ୍ ସ୍କ୍ରିନ୍ରେ ପ୍ରଦର୍ଶିତ କରିଥାଏ।"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"କେବଳ ପୁଲ୍-ଡାଉନ୍ ସେଡ୍ରେ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଉପରେ ଫୋକସ୍ ରହିବା ପାଇଁ ଆପଣଙ୍କୁ ସାହାଯ୍ୟ କରିଥାଏ। ସର୍ବଦା ନୀରବ।"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"ପ୍ରାଥମିକତା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକର ତଳେ ଡିସ୍ପ୍ଲେ ହୁଏ। ସର୍ବଦା ନିରବ।"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"ପ୍ରାଥମିକତା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକର ତଳେ ଡିସ୍ପ୍ଲେ ହୁଏ। ସର୍ବଦା ନିରବ।"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"ପ୍ରାଥମିକତା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକର ତଳେ ଡିସ୍ପ୍ଲେ ହୁଏ। ସର୍ବଦା ନିରବ।"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ସାଉଣ୍ଡ୍ ଏବଂ ଏକ ଷ୍ଟାଟସ୍ ବାର୍ ଆଇକନ୍ ମାଧ୍ୟମରେ ଆପଣଙ୍କର ଧ୍ୟାନ ଆକର୍ଷିତ କରିଥାଏ। ଲକ୍ ସ୍କ୍ରିନ୍ରେ ଦେଖାଯାଇଥାଏ।"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପରିବର୍ତ୍ତନ କରିହେବ ନାହିଁ।"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"ଏଠାରେ ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକର ଗ୍ରୁପ୍ କନଫ୍ୟୁଗର୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"ବିଜ୍ଞପ୍ତି ପ୍ରକ୍ସୀ ହୋଇଛି"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"ଏହି ଆପ୍ କ୍ୟାମେରା ବ୍ୟବହାର କରୁଛି।"</string>
<string name="appops_microphone" msgid="741508267659494555">"ଏହି ଆପ୍, ମାଇକ୍ରୋଫୋନ୍ ବ୍ୟବହାର କରୁଛି।"</string>
@@ -714,7 +724,7 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"ବିଜ୍ଞପ୍ତି"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"କୀ\'ବୋର୍ଡ ସର୍ଟକଟ୍"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="8413348767825486492">"କୀ\'ବୋର୍ଡ୍ର ଲେଆଉଟ୍କୁ ବଦଳାନ୍ତୁ"</string>
- <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ଆପ୍ଲିକେଶନ୍"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ଆପ୍ଲିକେସନ୍"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"ସହାୟତା"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ବ୍ରାଉଜର୍"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ଯୋଗାଯୋଗ"</string>
@@ -911,6 +921,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଖୋଲନ୍ତୁ"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବବଲ୍ଗୁଡ଼ିକ ପାଇଁ ସେଟିଂସ୍"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g>ରୁ ବବ୍ଲ୍ଗୁଡ଼ିକୁ ଅନୁମତି ଦିଅନ୍ତୁ?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="no_bubbles" msgid="337101288173078247">"ପ୍ରତ୍ୟାଖ୍ୟାନ କରନ୍ତୁ"</string>
<string name="yes_bubbles" msgid="668809525728633841">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"ମୋତେ ପରେ ପଚାରନ୍ତୁ"</string>
@@ -921,4 +932,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"ଉପର-ଡାହାଣକୁ ନିଅନ୍ତୁ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"ତଳ ବାମକୁ ନିଅନ୍ତୁ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"ତଳ ଡାହାଣକୁ ନିଅନ୍ତୁ"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-or/strings_tv.xml b/packages/SystemUI/res/values-or/strings_tv.xml
index 2174dc9..11676f9 100644
--- a/packages/SystemUI/res/values-or/strings_tv.xml
+++ b/packages/SystemUI/res/values-or/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"ଛବି-ଭିତରେ-ଛବି"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"ପିକଚର୍-ଇନ୍-ପିକଚର୍"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(କୌଣସି ଟାଇଟଲ୍ ପ୍ରୋଗ୍ରାମ୍ ନାହିଁ)"</string>
<string name="pip_close" msgid="3480680679023423574">"PIP ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 223d9cc..fcabbaf 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -67,7 +67,7 @@
<string name="usb_disable_contaminant_detection" msgid="2103905315747120033">"USB ਚਾਲੂ ਕਰੋ"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਜ਼ੂਮ ਕਰੋ"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਸਟ੍ਰੈਚ ਕਰੋ"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਵੋ"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਚਾਲੂ"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> ਤੱਕ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"ਗੂੜ੍ਹਾ ਥੀਮ"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"ਦੁਬਾਰਾ ਨਾ ਦਿਖਾਓ"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"ਸਭ ਕਲੀਅਰ ਕਰੋ"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"ਸਰਲ ਸੂਚਨਾਵਾਂ"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"ਸਾਰੀਆਂ ਸਰਲ ਸੂਚਨਾਵਾਂ ਕਲੀਅਰ ਕਰੋ"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਵੱਲੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਰੋਕਿਆ ਗਿਆ"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ਹੁਣ ਚਾਲੂ ਕਰੋ"</string>
<string name="empty_shade_text" msgid="708135716272867002">"ਕੋਈ ਸੂਚਨਾਵਾਂ ਨਹੀਂ"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"ਸਕ੍ਰੀਨ ਪਿੰਨ ਕੀਤੀ"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"ਇਹ ਇਸ ਨੂੰ ਤਦ ਤੱਕ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਰੱਖਦਾ ਹੈ ਜਦ ਤੱਕ ਤੁਸੀਂ ਅਨਪਿੰਨ ਨਹੀਂ ਕਰਦੇ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਪਿੱਛੇ\' ਅਤੇ \'ਰੂਪ-ਰੇਖਾ\' ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਅਨਪਿੰਨ ਨਾ ਕੀਤੇ ਜਾਣ ਤੱਕ ਇਸਨੂੰ ਦਿਖਾਇਆ ਜਾਂਦਾ ਹੈ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਪਿੱਛੇ\' ਅਤੇ \'ਹੋਮ\' ਨੂੰ ਸਪੱਰਸ਼ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ।"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਅਨਪਿੰਨ ਨਾ ਕੀਤੇ ਜਾਣ ਤੱਕ ਇਸਨੂੰ ਦਿਖਾਇਆ ਜਾਂਦਾ ਹੈ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ ਅਤੇ ਫੜ ਕੇ ਰੱਖੋ।"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"ਇਹ ਇਸ ਨੂੰ ਤਦ ਤੱਕ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਰੱਖਦਾ ਹੈ ਜਦ ਤੱਕ ਤੁਸੀਂ ਅਨਪਿੰਨ ਨਹੀਂ ਕਰਦੇ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਰੂਪ-ਰੇਖਾ\' ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਅਨਪਿੰਨ ਨਾ ਕੀਤੇ ਜਾਣ ਤੱਕ ਇਸਨੂੰ ਦਿਖਾਇਆ ਜਾਂਦਾ ਹੈ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਹੋਮ\' ਨੂੰ ਸਪੱਰਸ਼ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ।"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"ਇਸ ਸਕ੍ਰੀਨ ਨੂੰ ਅਨਪਿੰਨ ਕਰਨ ਲਈ, \'ਪਿੱਛੇ\' ਅਤੇ \'ਰੂਪ-ਰੇਖਾ\' ਬਟਨਾਂ ਨੂੰ ਸਪੱਰਸ਼ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"ਕੀ ਇਸ ਐਪ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"ਸਰਲ"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"ਤਰਜੀਹੀ"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"ਹਮੇਸ਼ਾਂ ਖਾਮੋਸ਼। ਹੇਠਾਂ ਖਿੱਚੀ ਜਾਣ ਵਾਲੀ ਸੂਚੀ \'ਤੇ ਦਿਸਦੀ ਹੈ।"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"ਹਮੇਸ਼ਾਂ ਖਾਮੋਸ਼। ਹੇਠਾਂ ਖਿੱਚੀ ਜਾਣ ਵਾਲੀ ਸੂਚੀ ਅਤੇ ਸਥਿਤੀ ਪੱਟੀ \'ਤੇ ਦਿਸਦੀ ਹੈ।"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"ਹਮੇਸ਼ਾਂ ਖਾਮੋਸ਼। ਹੇਠਾਂ ਖਿੱਚੀ ਜਾਣ ਵਾਲੀ ਸੂਚੀ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਦੀ ਹੈ।"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"ਹਮੇਸ਼ਾਂ ਖਾਮੋਸ਼। ਹੇਠਾਂ ਖਿੱਚੀ ਜਾਣ ਵਾਲੀ ਸੂਚੀ, ਸਥਿਤੀ ਪੱਟੀ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਦੀ ਹੈ।"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"ਧੁਨੀ ਵਜਾਉਂਦੀ ਹੈ ਅਤੇ ਹੇਠਾਂ ਖਿੱਚੀ ਜਾਣ ਵਾਲੀ ਸੂਚੀ, ਸਥਿਤੀ ਪੱਟੀ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਦੀ ਹੈ।"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"ਸਿਰਫ਼ ਹੇਠਾਂ ਖਿੱਚੀ ਜਾਣ ਵਾਲੀ ਸੂਚੀ ਵਿਚਲੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਧਿਆਨ ਦੇਣ ਵਿੱਚ ਤੁਹਾਡੀ ਮਦਦ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। ਹਮੇਸ਼ਾਂ ਖਮੋਸ਼।"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"ਘੱਟ ਤਰਜੀਹ ਵਾਲੀਆਂ ਸੂਚਨਾਵਾਂ ਦਿਖਾਓ। ਹਮੇਸ਼ਾਂ ਖਮੋਸ਼।"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"ਘੱਟ ਤਰਜੀਹ ਵਾਲੀਆਂ ਸੂਚਨਾਵਾਂ ਦਿਖਾਓ। ਹਮੇਸ਼ਾਂ ਖਮੋਸ਼।"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"ਘੱਟ ਤਰਜੀਹ ਵਾਲੀਆਂ ਸੂਚਨਾਵਾਂ ਦਿਖਾਓ। ਹਮੇਸ਼ਾਂ ਖਮੋਸ਼।"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ਧੁਨੀ ਅਤੇ ਸਥਿਤੀ ਪੱਟੀ ਪ੍ਰਤੀਕ ਨਾਲ ਤੁਹਾਡਾ ਧਿਆਨ ਖਿੱਚਦੀ ਹੈ। ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਾਓ।"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਸੋਧਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ।"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"ਇਹ ਸੂਚਨਾਵਾਂ ਦਾ ਗਰੁੱਪ ਇੱਥੇ ਸੰਰੂਪਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"ਇੱਕ ਐਪ ਦੀ ਥਾਂ \'ਤੇ ਦੂਜੀ ਐਪ ਰਾਹੀਂ ਦਿੱਤੀ ਗਈ ਸੂਚਨਾ"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"ਇਹ ਐਪ ਕੈਮਰੇ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ।"</string>
<string name="appops_microphone" msgid="741508267659494555">"ਇਹ ਐਪ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ।"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਖੋਲ੍ਹੋ"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਬੁਲਬੁਲਿਆਂ ਲਈ ਸੈਟਿੰਗਾਂ"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੋਂ ਬੁਲਬੁਲੇ ਆਉਣ ਦਿਓ?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="no_bubbles" msgid="337101288173078247">"ਮਨ੍ਹਾ ਕਰੋ"</string>
<string name="yes_bubbles" msgid="668809525728633841">"ਕਰਨ ਦਿਓ"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"ਮੈਨੂੰ ਬਾਅਦ ਵਿੱਚ ਪੁੱਛੋ"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"ਉੱਪਰ ਵੱਲ ਸੱਜੇ ਲਿਜਾਓ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"ਹੇਠਾਂ ਵੱਲ ਖੱਬੇ ਲਿਜਾਓ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"ਹੇਠਾਂ ਵੱਲ ਸੱਜੇ ਲਿਜਾਓ"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 0e7cb0a..ed792f2 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -375,6 +375,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Włącz o <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Ciemny motyw"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"Komunikacja NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Komunikacja NFC jest wyłączona"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Komunikacja NFC jest włączona"</string>
@@ -456,6 +458,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Nie pokazuj ponownie"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Ukryj wszystkie"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Zarządzaj"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Subtelne powiadomienia"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Wyczyść wszystkie subtelne powiadomienia"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Powiadomienia wstrzymane przez tryb Nie przeszkadzać"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Rozpocznij teraz"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Brak powiadomień"</string>
@@ -535,6 +539,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekran jest przypięty"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, kliknij i przytrzymaj Wstecz oraz Przegląd."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, naciśnij i przytrzymaj Wstecz oraz Ekran główny."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Ekran będzie widoczny, dopóki go nie odepniesz. Przesuń palcem w górę i przytrzymaj, by odpiąć."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, kliknij i przytrzymaj Przegląd."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, naciśnij i przytrzymaj Ekran główny."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Aby odpiąć ten ekran, naciśnij i przytrzymaj przyciski Wstecz oraz Przegląd"</string>
@@ -646,14 +651,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Nadal pokazywać powiadomienia z tej aplikacji?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Subtelne"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Priorytetowe"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Zawsze wyciszone. Wyświetlane w obszarze powiadomień."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Zawsze wyciszone. Wyświetlane w obszarze powiadomień i na pasku stanu"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Zawsze wyciszone. Wyświetlane w obszarze powiadomień i na ekranie blokady."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Zawsze wyciszone. Wyświetlane w obszarze powiadomień, na pasku stanu i ekranie blokady."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Sygnalizowane dźwiękiem i wyświetlanie w obszarze powiadomień, na pasku stanu i ekranie blokady."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Pomaga Ci się skupić, wyświetlając powiadomienia tylko w obszarze powiadomień. Zawsze wyciszone."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Wyświetla pod powiadomieniami priorytetowymi. Zawsze wyciszone."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Wyświetla pod powiadomieniami priorytetowymi. Zawsze wyciszone."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Wyświetla pod powiadomieniami priorytetowymi. Zawsze wyciszone."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Zwraca Twoją uwagę dźwiękiem i ikoną na pasku stanu. Wyświetla na ekranie blokady."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Tych powiadomień nie można zmodyfikować."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Tej grupy powiadomień nie można tu skonfigurować"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Powiadomienie w zastępstwie"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Ta aplikacja używa aparatu."</string>
<string name="appops_microphone" msgid="741508267659494555">"Ta aplikacja używa mikrofonu."</string>
@@ -877,7 +885,7 @@
<string name="instant_apps_message_with_help" msgid="6179830437630729747">"Aplikacja została otwarta bez zainstalowania. Kliknij, by dowiedzieć się więcej."</string>
<string name="app_info" msgid="6856026610594615344">"O aplikacji"</string>
<string name="go_to_web" msgid="2650669128861626071">"Otwórz przeglądarkę"</string>
- <string name="mobile_data" msgid="7094582042819250762">"Komórkowa transmisja danych"</string>
+ <string name="mobile_data" msgid="7094582042819250762">"Dane mobilne"</string>
<string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="mobile_carrier_text_format" msgid="3241721038678469804">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string>
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi jest wyłączone"</string>
@@ -923,6 +931,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Otwórz: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Ustawienia dymków aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Zezwolić na dymki z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Zarządzaj"</string>
<string name="no_bubbles" msgid="337101288173078247">"Odmów"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Zezwól"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Zapytaj później"</string>
@@ -933,4 +942,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Przenieś w prawy górny róg"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Przenieś w lewy dolny róg"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Przenieś w prawy dolny róg"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index c048150..cfca798 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ativado às <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Até <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema escuro"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"A NFC está desativada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"A NFC está ativada"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Não mostrar novamente"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Limpar tudo"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Gerenciar"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notificações discretas"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Limpar todas as notificações discretas"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificações pausadas pelo modo \"Não perturbe\""</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Iniciar agora"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Sem notificações"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"A tela está fixada"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Visão geral e mantenha essas opções pressionadas para liberar."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Início e mantenha essas opções pressionadas para liberar."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Ela é mantida à vista até que seja liberada. Deslize para cima e a mantenha pressionada para liberar."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ela é mantida à vista até que seja liberada. Toque em Visão geral e mantenha essa opção pressionada para liberar."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Ela é mantida à vista até que seja liberada. Toque em Início e mantenha essa opção pressionada para liberar."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Para liberar esta tela, mantenha os botões Voltar e Visão geral pressionados"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuar mostrando notificações desse app?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Discreta"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Priorizada"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Sempre silenciosa. Exibida na aba suspensa."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Sempre silenciosa. Exibida na aba suspensa e na barra de status."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Sempre silenciosa. Exibida na aba suspensa e na tela de bloqueio."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Sempre silenciosa. Exibida na aba suspensa, barra de status e tela de bloqueio."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Emite sons e é exibida na aba suspensa, barra de status e tela de bloqueio."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Ajuda você a se concentrar, já que as notificações são exibidas apenas na aba suspensa. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Exibida abaixo das notificações prioritárias. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Exibida abaixo das notificações prioritárias. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Exibida abaixo das notificações prioritárias. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Chama sua atenção com sons e um ícone na barra de status. Exibida na tela de bloqueio."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Não é possível modificar essas notificações."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Não é possível configurar esse grupo de notificações aqui"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notificação salva no proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Este app está usando a câmera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Este app está usando o microfone."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Abrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Configurações de balões do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Permitir balões de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Gerenciar"</string>
<string name="no_bubbles" msgid="337101288173078247">"Negar"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Permitir"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Perguntar depois"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Mover para canto superior direito"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Mover para canto inferior esquerdo"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Mover para canto inferior direito"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 4bfc255..328c1fd 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ativada à(s) <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Até à(s) <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema escuro"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"O NFC está desativado"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"O NFC está ativado"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Não mostrar de novo"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Limpar tudo"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Gerir"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notificações discretas"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Limpar todas as notificações discretas"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificações colocadas em pausa pelo modo Não incomodar."</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Começar agora"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Sem notificações"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"O ecrã está fixado"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Esta opção mantém o item visível até o soltar. Toque sem soltar em Anterior e em Vista geral para soltar."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Esta opção mantém o item visível até o soltar. Toque sem soltar em Anterior e em Página inicial para soltar."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Esta opção mantém o item visível até o soltar. Deslize rapidamente para cima e mantenha o gesto para soltar."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Esta opção mantém o item visível até o soltar. Toque sem soltar em Vista geral para soltar."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Esta opção mantém o item visível até o soltar. Toque sem soltar em Página inicial para soltar."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Para soltar este ecrã, toque sem soltar nos botões Anterior e Vista geral."</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Pretende continuar a ver notificações desta aplicação?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Discretas"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritárias"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Sempre silenciosa. É apresentada no painel pendente."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Sempre silenciosa. É apresentada no painel pendente e na barra de estado."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Sempre silenciosa. É apresentada no painel pendente e no ecrã de bloqueio."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Sempre silenciosa. É apresentada no painel pendente, na barra de estado e no ecrã de bloqueio."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Emite som e é apresentada no painel pendente, na barra de estado e no ecrã de bloqueio."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Ajuda-o a concentrar-se com notificações apenas no painel pendente. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"É apresentada abaixo das notificações prioritárias. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"É apresentada abaixo das notificações prioritárias. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"É apresentada abaixo das notificações prioritárias. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Chama a sua atenção com som e um ícone na barra de estado. É apresentada no ecrã de bloqueio."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Não é possível modificar estas notificações."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Não é possível configurar este grupo de notificações aqui."</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notificação de aplicação proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Esta aplicação está a utilizar a câmara."</string>
<string name="appops_microphone" msgid="741508267659494555">"Esta aplicação está a utilizar o microfone."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Abrir a aplicação <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Definições dos balões da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Pretende permitir balões da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Gerir"</string>
<string name="no_bubbles" msgid="337101288173078247">"Recusar"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Permitir"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Perguntar depois"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Mover parte superior direita"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Mover p/ parte infer. esquerda"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Mover parte inferior direita"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index c048150..cfca798 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ativado às <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Até <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema escuro"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"A NFC está desativada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"A NFC está ativada"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Não mostrar novamente"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Limpar tudo"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Gerenciar"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notificações discretas"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Limpar todas as notificações discretas"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificações pausadas pelo modo \"Não perturbe\""</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Iniciar agora"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Sem notificações"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"A tela está fixada"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Visão geral e mantenha essas opções pressionadas para liberar."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Início e mantenha essas opções pressionadas para liberar."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Ela é mantida à vista até que seja liberada. Deslize para cima e a mantenha pressionada para liberar."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ela é mantida à vista até que seja liberada. Toque em Visão geral e mantenha essa opção pressionada para liberar."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Ela é mantida à vista até que seja liberada. Toque em Início e mantenha essa opção pressionada para liberar."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Para liberar esta tela, mantenha os botões Voltar e Visão geral pressionados"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuar mostrando notificações desse app?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Discreta"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Priorizada"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Sempre silenciosa. Exibida na aba suspensa."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Sempre silenciosa. Exibida na aba suspensa e na barra de status."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Sempre silenciosa. Exibida na aba suspensa e na tela de bloqueio."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Sempre silenciosa. Exibida na aba suspensa, barra de status e tela de bloqueio."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Emite sons e é exibida na aba suspensa, barra de status e tela de bloqueio."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Ajuda você a se concentrar, já que as notificações são exibidas apenas na aba suspensa. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Exibida abaixo das notificações prioritárias. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Exibida abaixo das notificações prioritárias. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Exibida abaixo das notificações prioritárias. Sempre silenciosa."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Chama sua atenção com sons e um ícone na barra de status. Exibida na tela de bloqueio."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Não é possível modificar essas notificações."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Não é possível configurar esse grupo de notificações aqui"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notificação salva no proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Este app está usando a câmera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Este app está usando o microfone."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Abrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Configurações de balões do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Permitir balões de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Gerenciar"</string>
<string name="no_bubbles" msgid="337101288173078247">"Negar"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Permitir"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Perguntar depois"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Mover para canto superior direito"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Mover para canto inferior esquerdo"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Mover para canto inferior direito"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 3f37b67..d673743 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -371,6 +371,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Activată la <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Până la <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Temă întunecată"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Serviciul NFC este dezactivat"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Serviciul NFC este activat"</string>
@@ -451,6 +453,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Nu se mai afișează"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Ștergeți toate notificările"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Gestionați"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Notificări discrete"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Ștergeți toate notificările discrete"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificări întrerupte prin „Nu deranja”"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Începeți acum"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Nicio notificare"</string>
@@ -530,6 +534,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Ecranul este fixat"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Astfel rămâne afișat până anulați fixarea. Atingeți lung opțiunile Înapoi și Recente pentru a anula fixarea."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Astfel rămâne afișat până anulați fixarea. Atingeți lung opțiunile Înapoi și Acasă pentru a anula fixarea."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Astfel rămâne afișat până anulați fixarea. Glisați în sus și țineți apăsat pentru a anula fixarea."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Astfel rămâne afișat până anulați fixarea. Atingeți lung opțiunea Recente pentru a anula fixarea."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Astfel rămâne afișat până anulați fixarea. Atingeți lung opțiunea Acasă pentru a anula fixarea."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Pentru a anula fixarea acestui ecran, atingeți lung butoanele Înapoi și Recente"</string>
@@ -641,14 +646,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Doriți să continuați afișarea notificărilor de la această aplicație?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Discret"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Cu prioritate"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Întotdeauna silențios. Se afișează în fereastra trasă în jos."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Întotdeauna silențios. Se afișează în fereastra trasă în jos și în bara de stare."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Întotdeauna silențios. Se afișează în fereastra trasă în jos și pe ecranul de blocare."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Întotdeauna silențios. Se afișează în fereastra trasă în jos, bara de stare și ecranul de blocare."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Emite un sunet și se afișează în fereastra trasă în jos, în bara de stare și pe ecranul de blocare."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Vă ajută să vă concentrați cu notificări doar în fereastra trasă în jos. Întotdeauna silențios."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Se afișează sub notificările prioritare. Întotdeauna silențios."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Se afișează sub notificările prioritare. Întotdeauna silențios."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Se afișează sub notificările prioritare. Întotdeauna silențios."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Vă atrage atenția cu sunete și o pictogramă în bara de stare. Se afișează pe ecranul de blocare."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Aceste notificări nu pot fi modificate."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Acest grup de notificări nu poate fi configurat aici"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Notificare prin proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Această aplicație folosește camera foto."</string>
<string name="appops_microphone" msgid="741508267659494555">"Această aplicație folosește microfonul."</string>
@@ -901,7 +909,7 @@
<string name="auto_saver_enabled_text" msgid="874711029884777579">"Economisirea bateriei se va activa automat imediat ce bateria scade sub <xliff:g id="PERCENTAGE">%d</xliff:g>%%."</string>
<string name="open_saver_setting_action" msgid="8314624730997322529">"Setări"</string>
<string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
- <string name="heap_dump_tile_name" msgid="9141031328971226374">"Date SysUI memorie"</string>
+ <string name="heap_dump_tile_name" msgid="9141031328971226374">"Extrageți memoria SysUI"</string>
<string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> folosește <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplicațiile folosesc <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -916,6 +924,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Accesați <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Setări pentru baloanele <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Permiteți baloanele de la <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Gestionați"</string>
<string name="no_bubbles" msgid="337101288173078247">"Refuzați"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Permiteți"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Întreabă-mă mai târziu"</string>
@@ -926,4 +935,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Mutați în dreapta sus"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Mutați în stânga jos"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Mutați în dreapta jos"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index eb9f98f..9593e4f 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -373,6 +373,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Включить в <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Тёмная тема"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"Модуль NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Модуль NFC отключен"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Модуль NFC включен"</string>
@@ -454,6 +456,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Больше не показывать"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Очистить все"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Настроить"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Беззвучные уведомления"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Отклонить все беззвучные уведомления"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"В режиме \"Не беспокоить\" уведомления заблокированы"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Начать"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Нет уведомлений"</string>
@@ -533,6 +537,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Блокировка в приложении включена"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопки \"Назад\" и \"Обзор\"."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопки \"Назад\" и \"Главный экран\"."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Экран будет зафиксирован, пока вы не отмените блокировку (для этого нужно провести вверх и удерживать)."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопку \"Обзор\"."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопку \"Главный экран\"."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Чтобы отменить блокировку, нажмите и удерживайте кнопки \"Назад\" и \"Обзор\""</string>
@@ -644,14 +649,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Показывать уведомления от этого приложения?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Беззвучные"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Приоритетные"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Всегда без звука. Появляются на панели уведомлений."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Всегда без звука. Появляются на панели уведомлений и в строке состояния."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Всегда без звука. Появляются на панели уведомлений и заблокированном экране."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Всегда без звука. Появляются на панели уведомлений, в строке состояния и на заблокированном экране."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Появляются со звуком на панели уведомлений, в строке состояния и на заблокированном экране."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Уведомления появляются только на специальной панели, чтобы вы не отвлекались. Всегда без звука."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Показ уведомлений с низким приоритетом. Всегда без звука."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Показ уведомлений с низким приоритетом. Всегда без звука."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Показ уведомлений с низким приоритетом. Всегда без звука."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"О наличии уведомлений можно узнать по специальному звуку и значку в строке состояния. Уведомления появляются на заблокированном экране."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Эти уведомления нельзя изменить."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Эту группу уведомлений нельзя настроить здесь."</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Уведомление отправлено через прокси-сервер."</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Это приложение использует камеру."</string>
<string name="appops_microphone" msgid="741508267659494555">"Это приложение использует микрофон."</string>
@@ -919,8 +927,9 @@
<string name="music_controls_no_title" msgid="5236895307087002011">"Без названия"</string>
<string name="restart_button_description" msgid="2035077840254950187">"Нажмите, чтобы перезапустить приложение и перейти в полноэкранный режим."</string>
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Открыть приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
- <string name="bubbles_settings_button_description" msgid="2970630476657287189">"Настройки всплывающих подсказок от приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
- <string name="bubbles_prompt" msgid="8807968030159469710">"Разрешить всплывающие подсказки от приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
+ <string name="bubbles_settings_button_description" msgid="2970630476657287189">"Настройки всплывающих уведомлений от приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
+ <string name="bubbles_prompt" msgid="8807968030159469710">"Разрешить всплывающие уведомления от приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Настроить"</string>
<string name="no_bubbles" msgid="337101288173078247">"Запретить"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Разрешить"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Напомнить позже"</string>
@@ -931,4 +940,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Перенести в правый верхний угол"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Перенести в левый нижний угол"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Перенести в правый нижний угол"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 82668bb..4d3f5dc 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>ට ක්රියාත්මකයි"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> තෙක්"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"අඳුරු තේමාව"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC අබලයි"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC සබලයි"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"නැවත නොපෙන්වන්න"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"සියල්ල හිස් කරන්න"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"කළමනාකරණය කරන්න"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"මෘදු දැනුම්දීම්"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"සියලු මෘදු දැනුම්දීම් හිස් කරන්න"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"බාධා නොකරන්න මගින් විරාම කරන ලද දැනුම්දීම්"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"දැන් අරඹන්න"</string>
<string name="empty_shade_text" msgid="708135716272867002">"දැනුම්දීම් නැත"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"තීරය අමුණන ලදි"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට දළ විශ්ලේෂණය ස්පර්ශ කර ආපසු අල්ලාගෙන සිටින්න."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට මුල් පිටුව ස්පර්ශ කර අල්ලාගෙන සිටින්න."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට ඉහළට ස්වයිප් කර අල්ලා සිටින්න."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට දළ විශ්ලේෂණය ස්පර්ශ කර අල්ලාගෙන සිටින්න."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට මුල් පිටුව ස්පර්ශ කර අල්ලාගෙන සිටින්න."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"මෙම තිර ඇමුණුම ගැලවීමට, දළ විශ්ලේෂණය බොත්තම් ස්පර්ශ කර අල්ලා ගෙන සිටින්න"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"මෙම යෙදුම වෙතින් දැනුම්දීම් පෙන්වමින් තබන්නද?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"මෘදු"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"ප්රමුඛ කළ"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"සැම විටම නිහඬයි. පහළ ඇදීමේ සෙවන තුළ සංදර්ශන කරයි."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"සැම විටම නිහඬයි. පහළ ඇදීමේ සෙවන සහ තත්ත්ව තීරුව තුළ සංදර්ශන කරයි."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"සැම විටම නිහඬයි. පහළ ඇදීමේ සෙවන සහ අඟුලු තිරය මත සංදර්ශන කරයි."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"සැම විටම නිහඬයි. පහළ ඇදීමේ සෙවන, තත්ත්ව තීරුව තුළ සහ අඟුලු තිරය මත සංදර්ශන කරයි."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"පහළ ඇදීමේ සෙවන, තත්ත්ව තීරුව සහ අඟුලු තිරය මත ශබ්ද සහ සංදර්ශන කරයි."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"ඔබට පහළට-ඇදීමේ වැස්මේ පමණක් දැනුම්දීම් සමඟ අවධානය යොමු කිරීමට උදවු කරයි. සැම විටම නිහඬයි."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"ප්රමුඛතා දැනුම්දීම්වලට පහළින් සංදර්ශනය වේ. සැම විටම නිහඬයි."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"ප්රමුඛතා දැනුම්දීම්වලට පහළින් සංදර්ශනය වේ. සැම විටම නිහඬයි."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"ප්රමුඛතා දැනුම්දීම්වලට පහළින් සංදර්ශනය වේ. සැම විටම නිහඬයි."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ශබ්දයක් සහ තත්ත්ව තීරු නිරූපකයක් සමඟින් ඔබේ අවධානය ලබා ගනී. අගුළු තිරයෙහි පෙන්වයි."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"මෙම දැනුම්දීම් වෙනස් කළ නොහැක."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"මෙම දැනුම්දීම් සමූහය මෙහි වින්යාස කළ නොහැක"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"ප්රොක්සි කළ දැනුම්දීම"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"මෙම යෙදුම කැමරාව භාවිතා කරයි."</string>
<string name="appops_microphone" msgid="741508267659494555">"මෙම යෙදුම මයික්රෆෝනය භාවිතා කරයි."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> විවෘත කරන්න"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> බුබුළු සඳහා සැකසීම්"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> වෙතින් බුබුළුවලට ඉඩ දෙන්නේද?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"කළමනා කරන්න"</string>
<string name="no_bubbles" msgid="337101288173078247">"ප්රතික්ෂේප කරන්න"</string>
<string name="yes_bubbles" msgid="668809525728633841">"ඉඩ දෙන්න"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"පසුව මගෙන් අසන්න"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"ඉහළ දකුණට ගෙන යන්න"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"පහළ වමට ගෙන යන්න"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"පහළ දකුණට ගෙන යන්න"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index d3c65f4..720b256 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -370,9 +370,11 @@
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nočný režim"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Zapne sa pri západe slnka"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Do východu slnka"</string>
- <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Zapne sa o <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Od <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tmavý motív"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je deaktivované"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je aktivované"</string>
@@ -454,6 +456,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Nabudúce nezobrazovať"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Vymazať všetko"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Spravovať"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Nenápadné upozornenia"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Vymazať všetky nenápadné upozornenia"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Upozornenia sú pozastavené režimom bez vyrušení"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Spustiť"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Žiadne upozornenia"</string>
@@ -533,6 +537,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Obrazovka je pripnutá"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Obsah bude pripnutý v zobrazení, dokým ho neuvoľníte. Uvoľníte ho stlačením a podržaním tlačidiel Späť a Prehľad."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Obsah bude pripnutý v zobrazení, dokým ho neuvoľníte. Uvoľníte ho pridržaním tlačidiel Späť a Domov."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Táto možnosť ponechá položku v zobrazení, dokým ju neodopnete. Odpojíte potiahnutím a pridržaním."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Obsah bude pripnutý v zobrazení, dokým ho neuvoľníte. Uvoľníte ho stlačením a podržaním tlačidla Prehľad."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Obsah bude pripnutý v zobrazení, dokým ho neuvoľníte. Uvoľníte ho pridržaním tlačidla Domov."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Ak chcete odopnúť túto obrazovku, pridržte tlačidlá Späť a Prehľad"</string>
@@ -644,14 +649,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Majú sa upozornenia z tejto aplikácie naďalej zobrazovať?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Nenápadné"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioritné"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Vždy potichu. Zobrazuje sa v rozbaľovacom paneli."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Vždy potichu. Zobrazuje sa v rozbaľovacom paneli a stavovom riadku."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Vždy potichu. Zobrazuje sa v rozbaľovacom paneli a na uzamknutej obrazovke."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Vždy potichu. Zobrazuje sa v rozbaľovacom paneli, stavovom riadku a na uzamknutej obrazovke."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Vydáva zvukový signál a zobrazuje sa v rozbaľovacom paneli, stavovom riadku a na uzamknutej obrazovke."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Pomáha sústrediť sa zobrazovaním upozornení iba v rozbaľovacom paneli. Vždy potichu."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Zobrazuje sa pod prioritnými upozorneniami. Vždy potichu."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Zobrazuje sa pod prioritnými upozorneniami. Vždy potichu."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Zobrazuje sa pod prioritnými upozorneniami. Vždy potichu."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Upúta zvukom a zobrazením ikony v stavovom riadku. Zobrazuje sa na uzamknutej obrazovke."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Tieto upozornenia sa nedajú upraviť."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Túto skupinu upozornení nejde na tomto mieste konfigurovať"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Približné upozornenie"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Táto aplikácia používa fotoaparát."</string>
<string name="appops_microphone" msgid="741508267659494555">"Táto aplikácia používa mikrofón."</string>
@@ -890,7 +898,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"Aplikácie sú spustené na pozadí"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Klepnutím zobrazíte podrobnosti o batérii a spotrebe dát"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"Chcete vypnúť mobilné dáta?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"Prostredníctvom operátora <xliff:g id="CARRIER">%s</xliff:g> nebudete mať prístup k dátam ani internetu. Internet bude k dispozícii iba cez Wi-Fi."</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"Nebudete mať prístup k dátam ani internetu prostredníctvom operátora <xliff:g id="CARRIER">%s</xliff:g>. Internet bude k dispozícii iba cez Wi‑Fi."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"váš operátor"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Nastavenia nemôžu overiť vašu odpoveď, pretože určitá aplikácia blokuje žiadosť o povolenie."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"Povoliť aplikácii <xliff:g id="APP_0">%1$s</xliff:g> zobrazovať rezy z aplikácie <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
@@ -921,6 +929,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Otvoriť <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Nastavenia bublín aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Povoliť bubliny z aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Spravovať"</string>
<string name="no_bubbles" msgid="337101288173078247">"Zamietnuť"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Povoliť"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Spýtať sa neskôr"</string>
@@ -931,4 +940,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Presunúť doprava nahor"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Presunúť doľava nadol"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Presunúť doprava nadol"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 1695fbb..d0a5f50 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -67,7 +67,7 @@
<string name="usb_disable_contaminant_detection" msgid="2103905315747120033">"Omogoči USB"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Povečava čez cel zaslon"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Raztegnitev čez zaslon"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"Posnetek zaslona"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Posnetek"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"Shranjev. posnetka zaslona ..."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"Shranjevanje posnetka zaslona ..."</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"Posnetek zaslona je shranjen"</string>
@@ -373,6 +373,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Vklop ob <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Temna tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Tehnologija NFC je onemogočena"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Tehnologija NFC je omogočena"</string>
@@ -454,6 +456,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Tega ne prikaži več"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Izbriši vse"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Upravljanje"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Diskretna obvestila"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Počisti vsa diskretna obvestila"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Prikazovanje obvestil je začasno zaustavljeno z načinom »ne moti«"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Začni zdaj"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Ni obvestil"</string>
@@ -533,6 +537,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Zaslon je pripet"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"S tem ostane zaslon viden, dokler ga ne odpnete. Če ga želite odpeti, hkrati pridržite gumba za nazaj in pregled."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"S tem ostane zaslon viden, dokler ga ne odpnete. Če ga želite odpeti, hkrati pridržite gumba za nazaj in za začetni zaslon."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"S tem ostane zaslon viden, dokler ga ne odpnete. Če ga želite odpeti, povlecite navzgor in pridržite."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"S tem ostane zaslon viden, dokler ga ne odpnete. Če ga želite odpeti, pridržite gumb za pregled."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"S tem ostane zaslon viden, dokler ga ne odpnete. Če ga želite odpeti, pridržite gumb za začetni zaslon."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Če želite odpeti ta zaslon, hkrati pridržite gumba za nazaj in za pregled."</string>
@@ -636,22 +641,25 @@
<string name="inline_block_button" msgid="8735843688021655065">"Blokiraj"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Prikazuj še naprej"</string>
<string name="inline_minimize_button" msgid="966233327974702195">"Minimiraj"</string>
- <string name="inline_silent_button_silent" msgid="6904727667411781466">"Brez zvočnega opozorila"</string>
+ <string name="inline_silent_button_silent" msgid="6904727667411781466">"Diskretno"</string>
<string name="inline_silent_button_stay_silent" msgid="6308371431217601009">"Še naprej prikazuj brez zvoka"</string>
<string name="inline_silent_button_alert" msgid="2449191160203602471">"Z zvočnim opozorilom"</string>
<string name="inline_silent_button_keep_alerting" msgid="327696842264359693">"Še naprej opozarjaj"</string>
<string name="inline_turn_off_notifications" msgid="8635596135532202355">"Izklopi obvestila"</string>
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Želite, da so obvestila te aplikacije še naprej prikazana?"</string>
- <string name="notification_silence_title" msgid="7352089096356977930">"Brez zvočnega opozorila"</string>
+ <string name="notification_silence_title" msgid="7352089096356977930">"Diskretno"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prednostno"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Vedno tiho. Prikaz na poteznem zaslonu z obvestili."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Vedno tiho. Prikaz na poteznem zaslonu z obvestili in v vrstici stanja."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Vedno tiho. Prikaz na poteznem zaslonu z obvestili in na zaklenjenem zaslonu."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Vedno tiho. Prikaz na poteznem zaslonu z obvestili, v vrstici stanja in na zaklenjenem zaslonu."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Zvok ter prikaz na poteznem zaslonu z obvestili, v vrstici stanja in na zaklenjenem zaslonu."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Nemoteč prikaz samo na poteznem zaslonu z obvestili. Vedno tiho."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Prikaz pod prednostnimi obvestili. Vedno tiho."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Prikaz pod prednostnimi obvestili. Vedno tiho."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Prikaz pod prednostnimi obvestili. Vedno tiho."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Opozarjanje z zvokom in ikono v vrstici stanja. Prikaz na zaklenjenem zaslonu."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Za ta obvestila ni mogoče spremeniti nastavitev."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Te skupine obvestil ni mogoče konfigurirati tukaj"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Posredovano obvestilo"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Ta aplikacija uporablja fotoaparat."</string>
<string name="appops_microphone" msgid="741508267659494555">"Ta aplikacija uporablja mikrofon."</string>
@@ -890,7 +898,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"Aplikacije, ki se izvajajo v ozadju"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Dotaknite se za prikaz podrobnosti porabe akumulatorja in prenosa podatkov"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"Želite izklopiti prenos podatkov v mobilnih omrežjih?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"Dostopa do podatkov ali interneta ne boste imeli prek <xliff:g id="CARRIER">%s</xliff:g>. Internet bo na voljo samo prek povezave Wi-Fi."</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"Prek operaterja <xliff:g id="CARRIER">%s</xliff:g> ne boste imeli dostopa do podatkovne povezave ali interneta. Internet bo na voljo samo prek povezave Wi-Fi."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"svojega operaterja"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Ker aplikacija zakriva zahtevo za dovoljenje, z nastavitvami ni mogoče preveriti vašega odziva."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"Želite dovoliti, da aplikacija <xliff:g id="APP_0">%1$s</xliff:g> prikaže izreze aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
@@ -921,6 +929,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Odpri aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Nastavitve za oblačke aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Želite dovoliti oblačke iz aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Upravljanje"</string>
<string name="no_bubbles" msgid="337101288173078247">"Zavrni"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Dovoli"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Vprašaj me pozneje"</string>
@@ -931,4 +940,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Premakni zgoraj desno"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Premakni spodaj levo"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Premakni spodaj desno"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 01b96d7..b4ec066 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Aktive në <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Deri në <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tema e errët"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC është çaktivizuar"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC është aktivizuar"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Mos e shfaq sërish"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Pastroji të gjitha"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Menaxho"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Njoftimet me rëndësi të ulët"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Pastro të gjitha njoftimet me rëndësi të ulët"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Njoftimet janë vendosur në pauzë nga modaliteti \"Mos shqetëso\""</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Fillo tani"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Asnjë njoftim"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekrani u gozhdua"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Prapa\" dhe \"Përmbledhje\" për ta hequr nga gozhdimi."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Prapa\" dhe \"Kreu\" për ta hequr nga gozhdimi."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Kjo e ruan në pamje deri sa ta zhgozhdosh. Rrëshqit shpejt lart dhe mbaje të shtypur për ta hequr zhgozhduar."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Përmbledhje\" për ta hequr nga gozhdimi."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Kreu\" për ta hequr nga gozhdimi."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Për të hequr gozhdimin e këtij ekrani, prek dhe mbaj butonat \"Prapa\" dhe \"Përmbledhja\"."</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Do të vazhdosh t\'i shfaqësh njoftimet nga ky aplikacion?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Me rëndësi të ulët"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Me prioritet"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Gjithmonë në heshtje. Shfaqet në strehën me tërheqje poshtë."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Gjithmonë në heshtje. Shfaqet në strehën me tërheqje poshtë dhe shiritin e statusit."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Gjithmonë në heshtje. Shfaqet në strehën me tërheqje poshtë dhe në ekranin e kyçjes."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Gjithmonë në heshtje. Shfaqet në strehën me tërheqje poshtë, shiritin e statusit dhe në ekranin e kyçjes."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Bën tinguj dhe shfaqet në strehën me tërheqje poshtë, shiritin e statusit dhe në ekranin e kyçjes."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Të ndihmon të përqendrohesh me njoftimet vetëm në panelin zbritës. Gjithmonë në heshtje."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Shfaqet nën njoftimet me përparësi. Gjithmonë në heshtje."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Shfaqet nën njoftimet me përparësi. Gjithmonë në heshtje."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Shfaqet nën njoftimet me përparësi. Gjithmonë në heshtje."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Të tërheq vëmendjen me tingull dhe një ikonë në shiritin e statusit. Shfaqet në ekranin e kyçjes."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Këto njoftime nuk mund të modifikohen."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Ky grup njoftimesh nuk mund të konfigurohet këtu"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Njoftim i dërguar me përfaqësues"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Ky aplikacion po përdor kamerën."</string>
<string name="appops_microphone" msgid="741508267659494555">"Ky aplikacion po përdor mikrofonin."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Hap <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Cilësimet për flluskat e <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Të lejohen flluskat nga <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Menaxho"</string>
<string name="no_bubbles" msgid="337101288173078247">"Refuzo"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Lejo"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Më pyet më vonë"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Lëviz lart djathtas"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Zhvendos poshtë majtas"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Lëvize poshtë djathtas"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 81d88c7..afdedc2 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -208,10 +208,10 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Обавештење је одбачено."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Прозор са обавештењима."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Брза подешавања."</string>
- <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"Закључани екран."</string>
+ <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"Закључан екран."</string>
<string name="accessibility_desc_settings" msgid="3417884241751434521">"Подешавања"</string>
<string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"Преглед."</string>
- <string name="accessibility_desc_work_lock" msgid="4288774420752813383">"Закључани екран за посао"</string>
+ <string name="accessibility_desc_work_lock" msgid="4288774420752813383">"Закључан екран за посао"</string>
<string name="accessibility_desc_close" msgid="7479755364962766729">"Затвори"</string>
<string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wi-Fi је искључен."</string>
@@ -371,6 +371,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Укључује се у <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Тамна тема"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC је онемогућен"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC је омогућен"</string>
@@ -451,6 +453,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Не приказуј поново"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Обриши све"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Управљајте"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Дискретна обавештења"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Обришите сва дискретна обавештења"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Обавештења су паузирана режимом Не узнемиравај"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Започни одмах"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Нема обавештења"</string>
@@ -530,6 +534,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Екран је закачен"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"На овај начин се ово стално приказује док га не откачите. Додирните и задржите Назад и Преглед да бисте га откачили."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"На овај начин се ово стално приказује док га не откачите. Додирните и задржите Назад и Почетна да бисте га откачили."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"На овај начин се стално приказује док га не откачите. Превуците нагоре и задржите да бисте га откачили."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"На овај начин се ово стално приказује док га не откачите. Додирните и задржите Преглед да бисте га откачили."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"На овај начин се ово стално приказује док га не откачите. Додирните и задржите Почетна да бисте га откачили."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Да бисте откачили овај екран, додирните и задржите дугмад Назад и Преглед"</string>
@@ -641,14 +646,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Желите ли да се обавештења из ове апликације и даље приказују?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Дискретно"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Приоритетно"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Увек нечујно. Приказује се на падајућој траци."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Увек нечујно. Приказује се на падајућој траци и статусној траци."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Увек нечујно. Приказује се на падајућој траци и закључаном екрану."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Увек нечујно. Приказује се на падајућој траци, статусној траци и закључаном екрану."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Приказује се на падајућој траци, статусној траци и закључаном екрану уз звучно обавештење."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Помаже вам да се фокусирате. Обавештења су само на падајућој траци. Увек нечујно."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Приказује се испод приоритетних обавештења. Увек нечујно."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Приказује се испод приоритетних обавештења. Увек нечујно."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Приказује се испод приоритетних обавештења. Увек нечујно."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Привлачи вам пажњу помоћу звука и иконе статусне траке. Приказује се на закључаном екрану."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Ова обавештења не могу да се мењају."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Ова група обавештења не може да се конфигурише овде"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Обавештење преко проксија"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Ова апликација користи камеру."</string>
<string name="appops_microphone" msgid="741508267659494555">"Ова апликација користи микрофон."</string>
@@ -822,7 +830,7 @@
<string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Отвори подешавања за <xliff:g id="ID_1">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Измени редослед подешавања."</string>
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. страна од <xliff:g id="ID_2">%2$d</xliff:g>"</string>
- <string name="tuner_lock_screen" msgid="5755818559638850294">"Закључани екран"</string>
+ <string name="tuner_lock_screen" msgid="5755818559638850294">"Закључан екран"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Прошири"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Умањи"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Затвори"</string>
@@ -916,6 +924,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Отворите <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Подешавања за <xliff:g id="APP_NAME">%1$s</xliff:g> облачиће"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Желите ли да омогућите облачиће из апликације <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Управљајте"</string>
<string name="no_bubbles" msgid="337101288173078247">"Одбиј"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Дозволи"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Питај ме касније"</string>
@@ -926,4 +935,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Премести горе десно"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Премести доле лево"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Премести доле десно"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 0df3549..5c3f2f4 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"På från <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Till <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Mörkt tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC är inaktiverat"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC är aktiverat"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Visa inte igen"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Rensa alla"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Hantera"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Aviseringar utan avbrott"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Rensa alla aviseringar utan avbrott"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Aviseringar har pausats via Stör ej"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Starta nu"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Inga aviseringar"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Skärmen har fästs"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Skärmen visas tills du lossar den. Tryck länge på Tillbaka och Översikt om du vill lossa skärmen."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Skärmen visas tills du lossar den. Tryck länge på Tillbaka och Startsida om du vill lossa skärmen."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Skärmen visas tills du lossar den. Svep uppåt och håll kvar fingret om du vill lossa skärmen."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Skärmen visas tills du lossar den. Tryck länge på Översikt om du vill lossa skärmen."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Skärmen visas tills du lossar den. Tryck länge på Startsida om du vill lossa skärmen."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Om du vill lossa skärmen trycker du länge på knapparna Tillbaka och Översikt"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Vill du fortsätta visa aviseringar för den här appen?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Utan avbrott"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Prioriterade"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Alltid tyst. Visas på aviseringspanelen."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Alltid tyst. Visas på aviseringspanelen och i statusfältet."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Alltid tyst. Visas på aviseringspanelen och låsskärmen."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Alltid tyst. Visas på aviseringspanelen, i statusfältet och på låsskärmen."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Ljuder och visas på aviseringspanelen, i statusfältet och på låsskärmen."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Aviseringar visas bara på aviseringspanelen så att du kan fokusera på det viktigaste. Alltid tyst."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Aviseringar med låg prioritet visas. Alltid tyst."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Aviseringar med låg prioritet visas. Alltid tyst."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Aviseringar med låg prioritet visas. Alltid tyst."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Fångar din uppmärksamhet med ljud och en ikon i statusfältet. Visas på låsskärmen."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Det går inte att ändra de här aviseringarna."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Den här aviseringsgruppen kan inte konfigureras här"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Avisering via proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Kameran används av appen."</string>
<string name="appops_microphone" msgid="741508267659494555">"Mikrofonen används av appen."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Öppna <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Inställningar för <xliff:g id="APP_NAME">%1$s</xliff:g>-bubblor"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Vill du tillåta bubblor från <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Hantera"</string>
<string name="no_bubbles" msgid="337101288173078247">"Neka"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Tillåt"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Fråga senare"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Flytta högst upp till höger"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Flytta längst ned till vänster"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Flytta längst ned till höger"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 04dffd3..a772af2 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Itawashwa saa <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Hadi <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Mandhari Meusi"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC imezimwa"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC imewashwa"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Usionyeshe tena"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Futa zote"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Dhibiti"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Arifa zisizo na sauti"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Futa arifa zote zisizo na sauti"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Kipengele cha Usinisumbue kimesitisha arifa"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Anza sasa"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Hakuna arifa"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Skrini imebandikwa"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Hali hii huifanya ionekane hadi utakapoibandua. Gusa na ushikilie kipengele cha Nyuma na Muhtasari ili ubandue."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Hali hii huifanya ionekane hadi utakapoibandua. Gusa na ushikilie kitufe cha kurudisha Nyuma na cha Mwanzo kwa pamoja ili ubandue."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Hali hii huifanya ionekane hadi utakapoibandua. Telezesha kidole juu na ushikilie ili uibandue."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Hali hii huifanya ionekane hadi utakapoibandua. Gusa na ushikilie kipengele cha Muhtasari ili ubandue."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Hali hii huifanya ionekane hadi utakapoibandua. Gusa na ushikilie kitufe cha Mwanzo ili ubandue."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Ili ubandue skrini hii, gusa na ushikilie kitufe cha Nyuma na Muhtasari"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Ungependa kuendelea kuonyesha arifa kutoka programu hii?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Bila sauti"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Zilizopewa kipaumbele"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Kimya kila wakati. Huonyeshwa katika orodha kunjuzi."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Kimya kila wakati. Huonyeshwa katika orodha kunjuzi na kwenye sehemu ya arifa."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Kimya kila wakati. Huonyeshwa katika orodha kunjuzi na kwenye skrini iliyofungwa."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Kimya kila wakati. Huonyeshwa katika orodha kunjuzi, sehemu ya arifa na kwenye skrini iliyofungwa."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Hutoa sauti na kuonyeshwa katika orodha kunjuzi, sehemu ya arifa na kwenye skrini iliyofungwa."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Hukusaidia kuangazia arifa pekee kwenye orodha kunjuzi. Kimya kila wakati."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Huonyeshwa chini ya arifa za kipaumbele. Kimya kila wakati."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Huonyeshwa chini ya arifa za kipaumbele. Kimya kila wakati."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Huonyeshwa chini ya arifa za kipaumbele. Kimya kila wakati."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Hupata umakinifu wako kwa sauti na aikoni ya sehemu ya arifa. Huonyeshwa kwenye skrini iliyofungwa."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Arifa hizi haziwezi kubadilishwa."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Kikundi hiki cha arifa hakiwezi kuwekewa mipangilio hapa"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Arifa wakilishi"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Programu hii inatumia kamera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Programu hii inatumia maikrofoni."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Fungua <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Mipangilio ya viputo vya <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Je, ungependa kuruhusu viputo kutoka <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Dhibiti"</string>
<string name="no_bubbles" msgid="337101288173078247">"Kataa"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Ruhusu"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Niulize baadaye"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Sogeza juu kulia"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Sogeza chini kushoto"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Sogeza chini kulia"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index f828d15..6124f07 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -50,7 +50,7 @@
<string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ஐ அணுக, <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸை அனுமதிக்கவா?"</string>
<string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐக் கையாள, <xliff:g id="APPLICATION">%1$s</xliff:g> பயன்பாட்டைத் திறக்கவா?"</string>
<string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ஐக் கையாள, <xliff:g id="APPLICATION">%1$s</xliff:g> பயன்பாட்டைத் திறக்கவா?"</string>
- <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"நிறுவிய பயன்பாடுகள் எதுவும், USB துணைக்கருவியுடன் இயங்காது. <xliff:g id="URL">%1$s</xliff:g> இல் துணைக்கருவி குறித்து மேலும் அறிக"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"நிறுவிய ஆப்ஸ் எதுவும், USB துணைக்கருவியுடன் இயங்காது. <xliff:g id="URL">%1$s</xliff:g> இல் துணைக்கருவி குறித்து மேலும் அறிக"</string>
<string name="title_usb_accessory" msgid="4966265263465181372">"USB துணைக்கருவி"</string>
<string name="label_view" msgid="6304565553218192990">"காட்சி"</string>
<string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> இணைக்கப்பட்டிருக்கையில், <xliff:g id="APPLICATION">%1$s</xliff:g>ஐ எப்போதும் திற"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>க்கு ஆன் செய்"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> வரை"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"டார்க் தீம்"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC முடக்கப்பட்டது"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC இயக்கப்பட்டது"</string>
@@ -448,6 +450,10 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"மீண்டும் காட்டாதே"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"எல்லாவற்றையும் அழி"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"அறிவிப்புகளை நிர்வகி"</string>
+ <!-- no translation found for notification_section_header_gentle (8356064473678167305) -->
+ <skip />
+ <!-- no translation found for accessibility_notification_section_header_gentle_clear_all (4270384919249494640) -->
+ <skip />
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\'தொந்தரவு செய்ய வேண்டாம்\' அம்சத்தின் மூலம் அறிவிப்புகள் இடைநிறுத்தப்பட்டுள்ளன"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"இப்போது தொடங்கு"</string>
<string name="empty_shade_text" msgid="708135716272867002">"அறிவிப்புகள் இல்லை"</string>
@@ -507,7 +513,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"<xliff:g id="APPLICATION">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள். இந்தப் பயன்பாட்டால் மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் தனிப்பட்ட நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"உங்கள் பணிக் கணக்கை <xliff:g id="ORGANIZATION">%1$s</xliff:g> நிர்வகிக்கிறது. மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் பணி நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION">%2$s</xliff:g> உடன் அது இணைக்கப்பட்டுள்ளது.\n\nமேலும் தகவலுக்கு, நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"உங்கள் பணிக் கணக்கை <xliff:g id="ORGANIZATION">%1$s</xliff:g> நிர்வகிக்கிறது. மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் பணி நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> உடன் அது இணைக்கப்பட்டுள்ளது.\n\nஉங்கள் தனிப்பட்ட நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> உடனும் இணைக்கப்பட்டுள்ளீர்கள்."</string>
- <string name="keyguard_indication_trust_unlocked" msgid="2712865815371519117">"TrustAgent இதை லாக் செய்யவில்லை"</string>
+ <string name="keyguard_indication_trust_unlocked" msgid="2712865815371519117">"TrustAgent இதைத் திறந்தே வைத்துள்ளது"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"நீங்கள் கைமுறையாகத் திறக்கும் வரை, சாதனம் பூட்டப்பட்டிருக்கும்"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"விரைவாக அறிவிப்புகளைப் பெறுதல்"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"திறக்கும் முன் அவற்றைப் பார்க்கவும்"</string>
@@ -527,6 +533,8 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"திரை பொருத்தப்பட்டது"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"பொருத்தியதை அகற்றும் வரை இதைக் காட்சியில் வைக்கும். அகற்ற, முந்தையது மற்றும் மேலோட்டப் பார்வையைத் தொட்டுப் பிடிக்கவும்."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"இதற்கான பின்னை அகற்றும் வரை, இந்தப் பயன்முறை செயல்பாட்டிலேயே இருக்கும். அகற்றுவதற்கு, முந்தையது மற்றும் முகப்புப் பொத்தான்களைத் தொட்டுப் பிடிக்கவும்."</string>
+ <!-- no translation found for screen_pinning_description_gestural (1191513974909607884) -->
+ <skip />
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"பொருத்தியதை அகற்றும் வரை இதைக் காட்சியில் வைக்கும். அகற்ற, மேலோட்டப் பார்வையைத் தொட்டுப் பிடிக்கவும்."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"இதற்கான பின்னை அகற்றும் வரை, இந்தப் பயன்முறை செயல்பாட்டிலேயே இருக்கும். அகற்றுவதற்கு, முகப்புப் பொத்தானைத் தொட்டுப் பிடிக்கவும்."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"இந்தத் திரையின் பின்னை அகற்ற, முந்தையது மற்றும் மேலோட்டப் பார்வைப் பொத்தான்களைத் தொட்டுப் பிடிக்கவும்"</string>
@@ -636,24 +644,19 @@
<string name="inline_silent_button_keep_alerting" msgid="327696842264359693">"தொடர்ந்து விழிப்பூட்டு"</string>
<string name="inline_turn_off_notifications" msgid="8635596135532202355">"அறிவிப்புகளை முடக்கு"</string>
<string name="inline_keep_showing_app" msgid="1723113469580031041">"இந்தப் பயன்பாட்டின் அறிவிப்புகளைத் தொடர்ந்து காட்டவா?"</string>
- <!-- no translation found for notification_silence_title (7352089096356977930) -->
- <skip />
- <!-- no translation found for notification_alert_title (3966526305405016221) -->
- <skip />
- <!-- no translation found for notification_channel_summary_low (8816251796432620434) -->
- <skip />
- <!-- no translation found for notification_channel_summary_low_status (838359173060008373) -->
- <skip />
- <!-- no translation found for notification_channel_summary_low_lock (1568361562011497978) -->
- <skip />
- <!-- no translation found for notification_channel_summary_low_status_lock (966512668777695595) -->
- <skip />
- <!-- no translation found for notification_channel_summary_default (619096010741301745) -->
- <skip />
- <!-- no translation found for notification_unblockable_desc (4556908766584964102) -->
- <skip />
+ <string name="notification_silence_title" msgid="7352089096356977930">"ஜென்டில்"</string>
+ <string name="notification_alert_title" msgid="3966526305405016221">"முன்னுரிமைப்படுத்தப்பட்டது"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"கீழ் இழுக்கும் ஷேடில் வரும் அறிவிப்புகளில் மட்டும் கவனம் செலுத்த உதவுகிறது. எப்போதும் நிசப்தம்."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"குறைந்த முன்னுரிமைப் பெற்ற அறிவிப்புகளைக் காட்டும். எப்போதும் நிசப்தம்."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"குறைந்த முன்னுரிமைப் பெற்ற அறிவிப்புகளைக் காட்டும். எப்போதும் நிசப்தம்."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"குறைந்த முன்னுரிமைப் பெற்ற அறிவிப்புகளைக் காட்டும். எப்போதும் நிசப்தம்."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ஒலி & நிலைப் பட்டி ஐகான் மூலம் உங்கள் கவனத்தைப் பெறுகிறது. பூட்டுத் திரையில் காட்டும்."</string>
+ <string name="notification_unblockable_desc" msgid="4556908766584964102">"இந்த அறிவிப்புகளை மாற்ற இயலாது."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"இந்த அறிவுப்புக் குழுக்களை இங்கே உள்ளமைக்க இயலாது"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"ப்ராக்ஸியான அறிவிப்பு"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"இந்த ஆப்ஸானது கேமராவை உபயோகிக்கிறது."</string>
<string name="appops_microphone" msgid="741508267659494555">"இந்த ஆப்ஸானது, மைக்ரோஃபோனை உபயோகிக்கிறது."</string>
@@ -871,7 +874,7 @@
<string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> இயங்குகிறது"</string>
<string name="instant_apps_message" msgid="1183313016396018086">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது."</string>
<string name="instant_apps_message_with_help" msgid="6179830437630729747">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது. மேலும் அறியத் தட்டவும்."</string>
- <string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
+ <string name="app_info" msgid="6856026610594615344">"ஆப்ஸ் தகவல்"</string>
<string name="go_to_web" msgid="2650669128861626071">"உலாவிக்குச் செல்"</string>
<string name="mobile_data" msgid="7094582042819250762">"மொபைல் டேட்டா"</string>
<string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -888,7 +891,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"பின்னணியில் இயங்கும் பயன்பாடுகள்"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"பேட்டரி மற்றும் டேட்டா உபயோக விவரங்களைக் காண, தட்டவும்"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"மொபைல் டேட்டாவை ஆஃப் செய்யவா?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"<xliff:g id="CARRIER">%s</xliff:g> மொபைல் நிறுவனத்தின் மூலம் டேட்டா அல்லது இணையத்தை உங்களால் பயன்படுத்த முடியாது. வைஃபை வழியாக மட்டுமே இணையத்தைப் பயன்படுத்த முடியும்."</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"<xliff:g id="CARRIER">%s</xliff:g> மூலம் டேட்டா அல்லது இணையத்தை உங்களால் பயன்படுத்த முடியாது. வைஃபை வழியாக மட்டுமே இணையத்தைப் பயன்படுத்த முடியும்."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"உங்கள் மொபைல் நிறுவனம்"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"அனுமதிக் கோரிக்கையை ஆப்ஸ் மறைப்பதால், அமைப்புகளால் உங்கள் பதிலைச் சரிபார்க்க முடியாது."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> ஆப்ஸை, <xliff:g id="APP_2">%2$s</xliff:g> பயன்பாட்டின் விழிப்பூட்டல்களைக் காண்பிக்க அனுமதிக்கவா?"</string>
@@ -919,6 +922,8 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸைத் திறக்கும்"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> குமிழ்களுக்கான அமைப்புகள்"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸிலிருந்து குமிழ்களை அனுமதிக்கவா?"</string>
+ <!-- no translation found for manage_bubbles_text (7027739766859191408) -->
+ <skip />
<string name="no_bubbles" msgid="337101288173078247">"நிராகரி"</string>
<string name="yes_bubbles" msgid="668809525728633841">"அனுமதி"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"பிறகு கேள்"</string>
@@ -929,4 +934,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"மேலே வலப்புறமாக நகர்த்து"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"கீழே இடப்புறமாக நகர்த்து"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"கீழே வலதுபுறமாக நகர்த்து"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 0b1c78e..d2b117c 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>కి"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> వరకు"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"ముదురు రంగు థీమ్"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC నిలిపివేయబడింది"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ప్రారంభించబడింది"</string>
@@ -448,6 +450,10 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"మళ్లీ చూపవద్దు"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"అన్నీ క్లియర్ చేయండి"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"నిర్వహించండి"</string>
+ <!-- no translation found for notification_section_header_gentle (8356064473678167305) -->
+ <skip />
+ <!-- no translation found for accessibility_notification_section_header_gentle_clear_all (4270384919249494640) -->
+ <skip />
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"అంతరాయం కలిగించవద్దు ద్వారా నోటిఫికేషన్లు పాజ్ చేయబడ్డాయి"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ఇప్పుడే ప్రారంభించు"</string>
<string name="empty_shade_text" msgid="708135716272867002">"నోటిఫికేషన్లు లేవు"</string>
@@ -527,6 +533,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"స్క్రీన్ పిన్ చేయబడింది"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"దీని వలన మీరు అన్పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్పిన్ చేయడానికి వెనుకకు మరియు స్థూలదృష్టి తాకి & అలాగే పట్టుకోండి."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"దీని వలన మీరు అన్పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్పిన్ చేయడానికి వెనుకకు మరియు హోమ్ని తాకి & అలాగే పట్టుకోండి."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"మీరు అన్పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్పిన్ చేయడానికి, పైకి స్వైప్ చేసి & పట్టుకోండి."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"దీని వలన మీరు అన్పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్పిన్ చేయడానికి స్థూలదృష్టిని తాకి & అలాగే పట్టుకోండి."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"దీని వలన మీరు అన్పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్పిన్ చేయడానికి హోమ్ని తాకి & అలాగే పట్టుకోండి."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"ఈ స్క్రీన్ను అన్పిన్ చేయడానికి, వెనుకకు మరియు అవలోకనం బటన్లను తాకి & అలాగే పట్టుకోండి"</string>
@@ -638,14 +645,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"ఈ యాప్ నుండి నోటిఫికేషన్లను చూపిస్తూ ఉండాలా?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"సాధారణ"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"ప్రాధాన్యం గలవి"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"ఎల్లప్పుడూ నిశబ్దంగా ఉంచు. కిందకు-లాగే షేడ్లో ప్రదర్శింపబడుతుంది."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"ఎల్లప్పుడూ నిశబ్దంగా ఉంచు. కిందకు-లాగే షేడ్ & స్థితి పట్టీలో ప్రదర్శింపబడుంది."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"ఎల్లప్పుడూ నిశబ్దంగా ఉంచు. కిందకు-లాగే షేడ్ & లాక్ స్క్రీన్లో ప్రదర్శింపబడుతుంది."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"ఎల్లప్పుడూ నిశబ్దంగా ఉంచు. కిందకు-లాగే షేడ్, స్థితి పట్టీ & లాక్ స్క్రీన్లో ప్రదర్శింపబడుతుంది."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"శబ్దం చేస్తుంది, కిందకు-లాగే షేడ్, స్థితి పట్టీ & లాక్ స్క్రీన్ లో.ప్రదర్శింపబడుతుంది."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"కిందకు-లాగే షేడ్లో కనిపించే నోటిఫికేషన్ల మాత్రమే ద్వారా దృష్టి కేంద్రీకరించడానికి మీకు సహాయపడుతుంది. ఎల్లప్పుడూ నిశబ్దంగా ఉంచు."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"ప్రాధాన్యత గల నోటిఫికేషన్ల దిగువన ప్రదర్శిస్తుంది. ఎల్లప్పుడూ నిశబ్దంగా ఉంచు."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"ప్రాధాన్యత గల నోటిఫికేషన్ల దిగువన ప్రదర్శిస్తుంది. ఎల్లప్పుడూ నిశబ్దంగా ఉంచు."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"ప్రాధాన్యత గల నోటిఫికేషన్ల దిగువన ప్రదర్శిస్తుంది. ఎల్లప్పుడూ నిశబ్దంగా ఉంచు."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"శబ్దం & స్టేటస్ బార్ చిహ్నం ద్వారా మీరు దృష్టి సారించేలా చేస్తుంది. లాక్ స్క్రీన్పై చూపుతుంది."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"ఈ నోటిఫికేషన్లను సవరించడం వీలుపడదు."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"ఈ నోటిఫికేషన్ల సమూహాన్ని ఇక్కడ కాన్ఫిగర్ చేయలేము"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"ప్రాక్సీ చేయబడిన నోటిఫికేషన్"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"ఈ యాప్ ఈ కెమెరాను ఉపయోగిస్తోంది."</string>
<string name="appops_microphone" msgid="741508267659494555">"ఈ యాప్ మైక్రోఫోన్ను ఉపయోగిస్తుంది."</string>
@@ -911,6 +921,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g>ని తెరువు"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> బబుల్ల సెట్టింగ్లు"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> నుండి బబుల్లను అనుమతించాలా?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"నిర్వహించండి"</string>
<string name="no_bubbles" msgid="337101288173078247">"తిరస్కరించు"</string>
<string name="yes_bubbles" msgid="668809525728633841">"అనుమతించు"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"నన్ను తర్వాత అడగు"</string>
@@ -921,4 +932,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"ఎగువ కుడివైపునకు జరుపు"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"దిగువ ఎడమవైపునకు తరలించు"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"దిగవు కుడివైపునకు జరుపు"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 0f8fec3..5d50b16 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -185,7 +185,7 @@
<string name="not_default_data_content_description" msgid="9194667237765917844">"ไม่ได้ตั้งค่าให้ใช้อินเทอร์เน็ตมือถือ"</string>
<string name="cell_data_off" msgid="1051264981229902873">"ปิด"</string>
<string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"การปล่อยสัญญาณบลูทูธ"</string>
- <string name="accessibility_airplane_mode" msgid="834748999790763092">"โหมดใช้งานบนเครื่องบิน"</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"โหมดบนเครื่องบิน"</string>
<string name="accessibility_vpn_on" msgid="5993385083262856059">"VPN เปิดอยู่"</string>
<string name="accessibility_no_sims" msgid="3957997018324995781">"ไม่มีซิมการ์ด"</string>
<string name="carrier_network_change_mode" msgid="8149202439957837762">"การเปลี่ยนเครือข่ายผู้ให้บริการ"</string>
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"เปิดเวลา <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"จนถึง <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"ธีมสีเข้ม"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ถูกปิดใช้งาน"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"เปิดใช้งาน NFC แล้ว"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"ไม่ต้องแสดงข้อความนี้อีก"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"ล้างทั้งหมด"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"จัดการ"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"การแจ้งเตือนช่วยจำ"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"ล้างการแจ้งเตือนช่วยจำทั้งหมด"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"หยุดการแจ้งเตือนชั่วคราวโดย \"ห้ามรบกวน\""</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"เริ่มเลย"</string>
<string name="empty_shade_text" msgid="708135716272867002">"ไม่มีการแจ้งเตือน"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"ตรึงหน้าจอแล้ว"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกตรึง แตะ \"กลับ\" และ \"ภาพรวม\" ค้างไว้เพื่อเลิกตรึง"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกตรึง แตะ \"กลับ\" และ \"หน้าแรก\" ค้างไว้เพื่อเลิกตรึง"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"วิธีนี้ช่วยให้เห็นหน้าจอตลอดจนกว่าจะเลิกตรึง เลื่อนขึ้นค้างไว้เพื่อเลิกตรึง"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกตรึง แตะ \"ภาพรวม\" ค้างไว้เพื่อเลิกตรึง"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกตรึง แตะ \"หน้าแรก\" ค้างไว้เพื่อเลิกตรึง"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"หากต้องการเลิกตรึงหน้าจอนี้ ให้แตะปุ่ม \"กลับ\" และ \"ภาพรวม\" ค้างไว้"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"แสดงการแจ้งเตือนจากแอปนี้ต่อไปไหม"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"แจ้งเตือนเบาๆ"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"สำคัญ"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"ปิดเสียงตลอดเวลา แสดงในหน้าต่างแบบเลื่อนลง"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"ปิดเสียงตลอดเวลา แสดงในหน้าต่างแบบเลื่อนลงและแถบสถานะ"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"ปิดเสียงตลอดเวลา แสดงในหน้าต่างแบบเลื่อนลงและในหน้าจอล็อก"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"ปิดเสียงตลอดเวลา แสดงในหน้าต่างแบบเลื่อนลง แถบสถานะ และในหน้าจอล็อก"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"ส่งเสียงและแสดงในหน้าต่างแบบเลื่อนลง แถบสถานะ และในหน้าจอล็อก"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"ช่วยให้คุณโฟกัสกับการแจ้งเตือนในหน้าต่างแบบเลื่อนลงเท่านั้น ปิดเสียงตลอดเวลา"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"แสดงใต้การแจ้งเตือนเรื่องสำคัญ ปิดเสียงตลอดเวลา"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"แสดงใต้การแจ้งเตือนเรื่องสำคัญ ปิดเสียงตลอดเวลา"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"แสดงใต้การแจ้งเตือนเรื่องสำคัญ ปิดเสียงตลอดเวลา"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"ดึงความสนใจของคุณด้วยเสียงและไอคอนในแถบสถานะ แสดงในหน้าจอล็อก"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"แก้ไขการแจ้งเตือนเหล่านี้ไม่ได้"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"การแจ้งเตือนกลุ่มนี้กำหนดค่าที่นี่ไม่ได้"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"การแจ้งเตือนที่ผ่านพร็อกซี"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"แอปนี้กำลังใช้กล้อง"</string>
<string name="appops_microphone" msgid="741508267659494555">"แอปนี้กำลังใช้ไมโครโฟน"</string>
@@ -880,7 +888,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"แอปที่กำลังทำงานในเบื้องหลัง"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"แตะเพื่อดูรายละเอียดเกี่ยวกับแบตเตอรี่และปริมาณการใช้อินเทอร์เน็ต"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"ปิดเน็ตมือถือไหม"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"คุณจะใช้เน็ตมือถือหรืออินเทอร์เน็ตผ่าน <xliff:g id="CARRIER">%s</xliff:g> ไม่ได้ และจะใช้อินเทอร์เน็ตได้ผ่าน Wi-Fi เท่านั้น"</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"คุณจะใช้เน็ตมือถือหรืออินเทอร์เน็ตผ่าน <xliff:g id="CARRIER">%s</xliff:g> ไม่ได้ แต่จะใช้ผ่าน Wi-Fi ได้เท่านั้น"</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"ผู้ให้บริการของคุณ"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"เนื่องจากแอปหนึ่งได้บดบังคำขอสิทธิ์ ระบบจึงไม่สามารถยืนยันคำตอบของคุณสำหรับการตั้งค่าได้"</string>
<string name="slice_permission_title" msgid="7465009437851044444">"อนุญาตให้ <xliff:g id="APP_0">%1$s</xliff:g> แสดงส่วนต่างๆ ของ <xliff:g id="APP_2">%2$s</xliff:g>"</string>
@@ -904,13 +912,14 @@
<string name="privacy_type_camera" msgid="1676604631892420333">"กล้องถ่ายรูป"</string>
<string name="privacy_type_location" msgid="6435497989657286700">"ตำแหน่ง"</string>
<string name="privacy_type_microphone" msgid="4153045784928554506">"ไมโครโฟน"</string>
- <string name="sensor_privacy_mode" msgid="8982771253020769598">"เซ็นเซอร์ปิดอยู่"</string>
+ <string name="sensor_privacy_mode" msgid="8982771253020769598">"ปิดเซ็นเซอร์"</string>
<string name="device_services" msgid="1191212554435440592">"บริการของอุปกรณ์"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"ไม่มีชื่อ"</string>
<string name="restart_button_description" msgid="2035077840254950187">"แตะเพื่อรีสตาร์ทแอปนี้และแสดงแบบเต็มหน้าจอ"</string>
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"เปิด <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"การตั้งค่าลูกโป่ง <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"อนุญาตลูกโป่งจาก <xliff:g id="APP_NAME">%1$s</xliff:g> ไหม"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"จัดการ"</string>
<string name="no_bubbles" msgid="337101288173078247">"ปฏิเสธ"</string>
<string name="yes_bubbles" msgid="668809525728633841">"อนุญาต"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"ถามฉันทีหลัง"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"ย้ายไปด้านขวาบน"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"ย้ายไปด้านซ้ายล่าง"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"ย้ายไปด้านขาวล่าง"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index c24297c..5be6a3b 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Mao-on sa ganap na <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Hanggang <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Madilim na Tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Naka-disable ang NFC"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Naka-enable ang NFC"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Huwag ipakitang muli"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"I-clear lahat"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Pamahalaan"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Mga banayad na notification"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"I-clear ang lahat ng banayad na notification"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Mga notification na na-pause ng Huwag Istorbohin"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Magsimula ngayon"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Walang mga notification"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Naka-pin ang screen"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Pinapanatili nitong nakikita ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Bumalik at Overview upang mag-unpin."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Pinapanatili nitong nakikita ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Bumalik at Home upang mag-unpin."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Pinapanatili nitong nakikita ito hanggang sa mag-unpin ka. Mag-swipe pataas at i-hold para i-unpin."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Pinapanatili nitong nakikita ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Overview upang mag-unpin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Pinapanatili nitong nakikita ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Home upang mag-unpin."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Upang i-unpin ang screen na ito, pindutin nang matagal ang mga button na Bumalik at Overview"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Patuloy na ipakita ang mga notification mula sa app na ito?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Malumanay"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Priyoridad"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Palaging naka-silent. Ipinapakita sa pull-down na shade."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Palaging naka-silent. Ipinapakita sa pull-down na shade at status bar."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Palaging naka-silent. Ipinapakita sa pull-down na shade at lock screen."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Palaging naka-silent. Ipinapakita sa pull-down na shade, status bar, at lock screen."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Tumutunog at ipinapakita sa pull-down na shade, status bar, at lock screen."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Nakakatulong para hindi ka maabala dahil sa pull-down na shade lang lalabas ang mga notification. Palaging naka-silent."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Ipinapakita sa ibaba ng mga priyoridad na notification. Palaging naka-silent."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Ipinapakita sa ibaba ng mga priyoridad na notification. Palaging naka-silent."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Ipinapakita sa ibaba ng mga priyoridad na notification. Palaging naka-silent."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Kinukuha ang iyong atensyon gamit ang tunog at icon sa status bar. Ipinapakita sa lock screen."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Hindi puwedeng baguhin ang mga notification na ito."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Hindi mako-configure dito ang pangkat na ito ng mga notification"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Na-proxy na notification"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Ginagamit ng app na ito ang camera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Ginagamit ng app na ito ang mikropono."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Buksan ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Mga setting para sa mga bubble ng <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Payagan ang mga bubble mula sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Pamahalaan"</string>
<string name="no_bubbles" msgid="337101288173078247">"Tanggihan"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Payagan"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Tanungin ako sa ibang pagkakataon"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Ilipat sa kanan sa itaas"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Ilipat sa kaliwa sa ibaba"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Ilipat sa kanan sa ibaba"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index b424ab2..7cfbb13 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Şu saatte açılacak: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Şu saate kadar: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Koyu Tema"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC devre dışı"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC etkin"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Bir daha gösterme"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Tümünü temizle"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Yönet"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Sessiz bildirimler"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Sessiz bildirimlerin tümünü temizle"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Bildirimler, Rahatsız Etmeyin özelliği tarafından duraklatıldı"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Şimdi başlat"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Bildirim yok"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekran sabitlendi"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Geri\'ye ve Genel Bakış\'a dokunup basılı tutun."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Geri\'ye ve Ana sayfaya dokunup basılı tutun."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Bu, sabitleme kaldırılana kadar öğenin görünmesini sağlar. Sabitlemeyi kaldırmak için yukarı kaydırıp basılı tutun."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Genel bakış\'a dokunup basılı tutun."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Ana sayfaya dokunup basılı tutun."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Bu ekranın sabitlemesini kaldırmak için Geri ve Genel Bakış düğmelerine dokunup basılı tutun"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Bu uygulamadan gelen bildirimler gösterilmeye devam edilsin mi?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Sessiz"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Öncelikli"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Her zaman sessiz. Aşağı açılır gölgede gösterilir."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Her zaman sessiz. Aşağı açılır gölgede ve durum çubuğunda gösterilir."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Her zaman sessiz. Aşağı açılır gölgede ve kilit ekranında gösterilir."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Her zaman sessiz. Aşağı açılır gölgede, durum çubuğunda ve kilit ekranında gösterilir."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Ses çıkarır. Ayrıca aşağı açılır gölgede, durum çubuğunda ve kilit ekranında gösterilir."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Bildirimleri yalnızca aşağıya açılır gölgede göstererek işinize odaklanmanızı sağlar. Her zaman sessizdir."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Öncelikli bildirimlerin altında görüntülenir. Her zaman sessizdir."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Öncelikli bildirimlerin altında görüntülenir. Her zaman sessizdir."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Öncelikli bildirimlerin altında görüntülenir. Her zaman sessizdir."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Ses ve bir durum çubuğu simgesiyle dikkatinizi çeker. Kilit ekranında gösterilir."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Bu bildirimler değiştirilemez."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Bu bildirim grubu burada yapılandırılamaz"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Proxy uygulanan bildirim"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Bu uygulama kamerayı kullanıyor."</string>
<string name="appops_microphone" msgid="741508267659494555">"Bu uygulama mikrofonu kullanıyor."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> öğesini açın."</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> baloncukları için ayarlar"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> baloncuklarına izin verilsin mi?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Yönet"</string>
<string name="no_bubbles" msgid="337101288173078247">"Reddet"</string>
<string name="yes_bubbles" msgid="668809525728633841">"İzin Ver"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Daha sonra yeniden sor"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Sağ üste taşı"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Sol alta taşı"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Sağ alta taşı"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 43fc2a7..9858a2c 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -340,7 +340,7 @@
<string name="quick_settings_cast_no_wifi" msgid="2696477881905521882">"Wi-Fi не під’єднано"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яскравість"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТО"</string>
- <string name="quick_settings_inversion_label" msgid="8790919884718619648">"Інвертувати кольори"</string>
+ <string name="quick_settings_inversion_label" msgid="8790919884718619648">"Інвертовані кольори"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"Режим коригування кольору"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"Більше налаштувань"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Готово"</string>
@@ -373,6 +373,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Вмикається о <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Темна тема"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC вимкнено"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ввімкнено"</string>
@@ -454,6 +456,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Більше не показувати"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Очистити все"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Керувати"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Тихі сповіщення"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Очистити всі тихі сповіщення"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Режим \"Не турбувати\" призупинив сповіщення"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Почати зараз"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Сповіщень немає"</string>
@@ -533,6 +537,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Екран закріплено"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Ви постійно бачитимете екран, доки не відкріпите його. Щоб відкріпити екран, натисніть і втримуйте кнопки \"Назад\" та \"Огляд\"."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Ви бачитимете цей екран, доки не відкріпите його. Для цього натисніть і утримуйте кнопки \"Назад\" та \"Головний екран\"."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Ви бачитимете цей екран, доки не відкріпите його. Для цього проведіть пальцем угору й утримуйте екран."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ви постійно бачитимете екран, доки не відкріпите його. Щоб відкріпити екран, натисніть і втримуйте кнопку \"Огляд\"."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Ви бачитимете цей екран, доки не відкріпите його. Для цього натисніть і утримуйте кнопку \"Головний екран\"."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Щоб відкріпити цей екран, натисніть і утримуйте кнопки \"Назад\" та \"Огляд\""</string>
@@ -644,14 +649,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Чи показувати сповіщення з цього додатка надалі?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Тихі сповіщення"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Пріоритетні сповіщення"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Завжди без звуку. Показуються на розкривній панелі."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Завжди без звуку. Показуються на розкривній панелі й у рядку стану."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Завжди без звуку. Показуються на розкривній панелі й на заблокованому екрані."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Завжди без звуку. Показуються на розкривній панелі, у рядку стану й на заблокованому екрані."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Подають сигнал і показуються на розкривній панелі, у рядку стану й на заблокованому екрані."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Сповіщення показуються лише на розкривній панелі, щоб не відволікати. Завжди без звуку."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Показуються під пріоритетними сповіщеннями. Завжди без звуку."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Показуються під пріоритетними сповіщеннями. Завжди без звуку."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Показуються під пріоритетними сповіщеннями. Завжди без звуку."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Привертають увагу сигналом і значком у рядку стану. Показуються на заблокованому екрані."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Ці сповіщення не можна змінити."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Цю групу сповіщень не можна налаштувати тут"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Проксі-сповіщення"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Цей додаток використовує камеру."</string>
<string name="appops_microphone" msgid="741508267659494555">"Цей додаток використовує мікрофон."</string>
@@ -921,6 +929,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Відкрити додаток <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Налаштування спливаючих підказок від додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Дозволити спливаючі підказки від додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Керувати"</string>
<string name="no_bubbles" msgid="337101288173078247">"Заборонити"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Дозволити"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Запитати пізніше"</string>
@@ -931,4 +940,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Перемістити праворуч угору"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Перемістити ліворуч униз"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Перемістити праворуч униз"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 596349f..4c1be1b 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"آن ہوگی بوقت <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> تک"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"گہری تھیم"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC غیر فعال ہے"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC فعال ہے"</string>
@@ -448,6 +450,10 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"دوبارہ نہ دکھائیں"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"سبھی کو صاف کریں"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"نظم کریں"</string>
+ <!-- no translation found for notification_section_header_gentle (8356064473678167305) -->
+ <skip />
+ <!-- no translation found for accessibility_notification_section_header_gentle_clear_all (4270384919249494640) -->
+ <skip />
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\'ڈسٹرب نہ کریں\' کے ذریعے اطلاعات کو موقوف کیا گیا"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ابھی شروع کریں"</string>
<string name="empty_shade_text" msgid="708135716272867002">"کوئی اطلاعات نہیں ہیں"</string>
@@ -527,6 +533,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"اسکرین پن کردہ ہے"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"یہ اسے اس وقت تک نظر میں رکھتا ہے جب تک آپ اس سے پن ہٹا نہیں دیتے۔ پن ہٹانے کیلئے پیچھے اور مجموعی جائزہ بٹنز کو ٹچ کریں اور دبائے رکھیں۔"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"یہ اس کو اس وقت تک مد نظر رکھتا ہے جب تک آپ اس سے پن نہیں ہٹا دیتے۔ پن ہٹانے کیلئے \"پیچھے\" اور \"ہوم\" بٹنز کو ٹچ کریں اور دبائے رکھیں۔"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"یہ اس کو اس وقت تک مد نظر رکھتا ہے جب تک آپ اس سے پن نہیں ہٹا دیتے۔ پن ہٹانے کے لیے سوائپ کریں اور پکڑ کر رکھیں۔"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"یہ اسے اس وقت تک نظر میں رکھتا ہے جب تک آپ اس سے پن ہٹا نہیں دیتے۔ پن ہٹانے کیلئے مجموعی جائزہ بٹن کو ٹچ کریں اور دبائے رکھیں۔"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"یہ اس کو اس وقت تک مد نظر رکھتا ہے جب تک آپ اس سے پن نہیں ہٹا دیتے۔ پن ہٹانے کیلئے \"ہوم\" بٹن کو ٹچ کریں اور دبائے رکھیں۔"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"اس اسکرین سے پن ہٹانے کیلئے، \"پیچھے\" اور \"مجموعی جائزہ\" بٹنز کو ٹچ کریں اور دبائے رکھیں"</string>
@@ -637,15 +644,18 @@
<string name="inline_turn_off_notifications" msgid="8635596135532202355">"اطلاعات کو آف کریں"</string>
<string name="inline_keep_showing_app" msgid="1723113469580031041">"اس ایپ کی طرف سے اطلاعات دکھانا جاری رکھیں؟"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"لطیف"</string>
- <string name="notification_alert_title" msgid="3966526305405016221">"ترجیح دی گئی"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"ہمیشہ خاموش رکھیں۔ نیچے کی طرف کھینچیں شیڈ میں ڈسپلے کرتا ہے۔"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"ہمیشہ خاموش رکھیں۔ نیچے کی طرف کھینچیں شیڈ اور اسٹیٹس بار پر ڈسپلے کرتا ہے۔"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"ہمیشہ خاموش رکھیں۔ نیچے کی طرف کھینچیں شیڈ اور مقفل اسکرین پر ڈسپلے کرتا ہے۔"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"ہمیشہ خاموش رکھیں۔ نیچے کی طرف کھینچیں شیڈ، اسٹیٹس بار اور مقفل اسکرین پر ڈسپلے کرتا ہے۔"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"نیچے کی طرف کھینچیں شیڈ، اسٹیٹس بار اور مقفل اسکرین پر آواز اور ڈسپلے کرتا ہے۔"</string>
+ <string name="notification_alert_title" msgid="3966526305405016221">"ترجیحی"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"صرف نیچے کی طرف کھینچیں شیڈ میں اطلاعات کے ساتھ فوکس کرنے میں آپ کی مدد کرتا ہے۔ ہمیشہ خاموش۔"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"کم ترجیحی اطلاعات ڈسپلے کرتا ہے۔ ہمیشہ خاموش۔"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"کم ترجیحی اطلاعات ڈسپلے کرتا ہے۔ ہمیشہ خاموش۔"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"کم ترجیحی اطلاعات ڈسپلے کرتا ہے۔ ہمیشہ خاموش۔"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"آواز اور اسٹیٹس بار کے آئیکن کے ساتھ آپ کی توجہ حاصل کرتا ہے۔ مقفل اسکرین پر دکھاتا ہے۔"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"ان اطلاعات کی ترمیم نہیں کی جا سکتی۔"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"اطلاعات کے اس گروپ کو یہاں کنفیگر نہیں کیا جا سکتا"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"پراکسی اطلاع"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"یہ ایپ کیمرے کا استعمال کر رہی ہے۔"</string>
<string name="appops_microphone" msgid="741508267659494555">"یہ ایپ مائیکروفون کا استعمال کر رہی ہے۔"</string>
@@ -911,6 +921,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> کھولیں"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> بلبلوں کے لیے ترتیبات"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> کی جانب سے بلبلوں کو اجازت دیں؟"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"نظم کریں"</string>
<string name="no_bubbles" msgid="337101288173078247">"مسترد کریں"</string>
<string name="yes_bubbles" msgid="668809525728633841">"اجازت دیں"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"مجھ سے بعد میں پوچھیں"</string>
@@ -921,4 +932,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"اوپر دائیں جانب لے جائيں"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"نیچے بائیں جانب لے جائیں"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"نیچے دائیں جانب لے جائیں"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 83962e3..52ca263 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> da yoqish"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> gacha"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Tungi mavzu"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC o‘chiq"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC yoniq"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Boshqa ko‘rsatilmasin"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Hammasini tozalash"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Boshqarish"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Tovushsiz bildirishnomalar"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Barcha tovushsiz bildirishnomalarni tozalash"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Bezovta qilinmasin rejimida bildirishnomalar pauza qilingan"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Boshlash"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Bildirishnomalar yo‘q"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekran qadaldi"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Ekran yechilmaguncha u o‘zgarmas holatda qoladi. Uni yechish uchun “Orqaga” va “Umumiy ma’lumot” tugmalarini bosib turing."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Ekran yechib olinmagunicha u mahkamlangan holatda qoladi. Uni yechish uchun Orqaga va Asosiy tugmalarni birga bosib turing."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Yechilmaguncha chiqib turadi. Yechish uchun tepaga suring va qoʻlingizni kerakli holatda tutib turing."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ekran yechilmaguncha u o‘zgarmas holatda qoladi. Uni yechish uchun “Umumiy ma’lumot” tugmasini bosib turing."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Ekran yechib olinmagunicha u mahkamlangan holatda qoladi. Uni yechish uchun Orqaga va Asosiy tugmlarni birga bosib turing."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Bu ekrandan chiqish uchun Orqaga va Menyu tugmalarini bosib turing"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Bu ilovadan keladigan bildirishnomalar chiqaversinmi?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Tovushsiz"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Muhim"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Doimo ovozsiz qolsin. Bildirishnomalar panelida chiqadi."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Doimo ovozsiz qolsin. Bildirishnomalar va holat panelida chiqadi"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Doimo ovozsiz qolsin. Bildirishnomalar paneli va ekran qulfida chiqadi"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Doimo ovozsiz qolsin. Bildirishnomalar paneli, holat panelida va ekran qulfida chiqadi"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Ovoz chiqarib, bildirishnomalar paneli, holat paneli va ekran qulfida chiqadi."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Bildirishnomalar faqat maxsus panelda chiqadi. Doim tovushsiz."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Muhimlik darajasi past bildirishnomalarning chiqishi. Doim tovushsiz."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Muhimlik darajasi past bildirishnomalarning chiqishi. Doim tovushsiz."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Muhimlik darajasi past bildirishnomalarning chiqishi. Doim tovushsiz."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Kelgan bildirishnomalarni maxsus tovush va holat paneliga chiqadigan nishoncha orqali bilish mumkin. Bildirishnomalar ekran qulfida ham chiqadi."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Bu bildirishnomalarni tahrirlash imkonsiz."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Ushbu bildirishnomalar guruhi bu yerda sozlanmaydi"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Ishonchli bildirishnoma"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Bu ilova kameradan foydalanmoqda."</string>
<string name="appops_microphone" msgid="741508267659494555">"Bu ilova mikrofondan foydalanmoqda."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Ochish: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g> pufakchalari uchun sozlamalar"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"<xliff:g id="APP_NAME">%1$s</xliff:g> pufakchalariga ruxsat berilsinmi?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Boshqarish"</string>
<string name="no_bubbles" msgid="337101288173078247">"Rad etish"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Ruxsat"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Keyinroq soʻralsin"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Yuqori oʻngga surish"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Quyi chapga surish"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Quyi oʻngga surish"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 4e4aeee..1150e16 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Bật vào lúc <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Cho đến <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Giao diện tối"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC đã được tắt"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC đã được bật"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Không hiển thị lại"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Xóa tất cả"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Quản lý"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Thông báo nhẹ nhàng"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Xóa tất cả thông báo nhẹ nhàng"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Chế độ Không làm phiền đã tạm dừng thông báo"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Bắt đầu ngay"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Không có thông báo nào"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Màn hình được ghim"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Thao tác này sẽ duy trì hiển thị màn hình cho đến khi bạn bỏ ghim. Hãy chạm và giữ Quay lại và Tổng quan để bỏ ghim."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Thao tác này sẽ duy trì hiển thị màn hình cho đến khi bạn bỏ ghim. Hãy chạm và giữ nút Quay lại và nút Màn hình chính để bỏ ghim."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Màn hình tiếp tục hiển thị cho tới khi bạn bỏ ghim. Hãy vuốt lên và giữ để bỏ ghim."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Thao tác này sẽ duy trì hiển thị màn hình cho đến khi bạn bỏ ghim. Hãy chạm và giữ Tổng quan để bỏ ghim."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Thao tác này sẽ duy trì hiển thị màn hình cho đến khi bạn bỏ ghim. Hãy chạm và giữ nút Màn hình chính để bỏ ghim."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Để bỏ ghim màn hình này, hãy chạm và giữ nút Quay lại và nút Tổng quan"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Tiếp tục hiển thị các thông báo từ ứng dụng này?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Nhẹ nhàng"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Ưu tiên"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Luôn im lặng. Hiển thị trong danh sách kéo xuống."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Luôn im lặng. Hiển thị trong danh sách kéo xuống và thanh trạng thái."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Luôn im lặng. Hiển thị trong danh sách kéo xuống và trên màn hình khóa."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Luôn im lặng. Hiển thị trong danh sách kéo xuống, thanh trạng thái và trên màn hình khóa."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Phát âm báo và hiển thị trong danh sách kéo xuống, thanh trạng thái và trên màn hình khóa."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Giúp bạn chỉ tập trung vào thông báo trong danh sách kéo xuống. Luôn im lặng."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Hiển thị bên dưới thông báo mức độ ưu tiên. Luôn im lặng."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Hiển thị bên dưới thông báo mức độ ưu tiên. Luôn im lặng."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Hiển thị bên dưới thông báo mức độ ưu tiên. Luôn im lặng."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Thu hút sự chú ý của bạn bằng biểu tượng thanh trạng thái và âm thanh. Hiển thị trên màn hình khóa."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Không thể sửa đổi các thông báo này."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Không thể định cấu hình nhóm thông báo này tại đây"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Thông báo đã xử lý qua máy chủ proxy"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Ứng dụng này đang sử dụng máy ảnh."</string>
<string name="appops_microphone" msgid="741508267659494555">"Ứng dụng này đang sử dụng micrô."</string>
@@ -880,7 +888,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"Ứng dụng đang chạy trong nền"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Nhấn để biết chi tiết về mức sử dụng dữ liệu và pin"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"Tắt dữ liệu di động?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"Bạn sẽ không có quyền truy cập vào dữ liệu hoặc Internet thông qua <xliff:g id="CARRIER">%s</xliff:g>. Bạn chỉ có thể truy cập Internet thông qua Wi-Fi."</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"Bạn sẽ không có quyền sử dụng dữ liệu hoặc truy cập Internet thông qua <xliff:g id="CARRIER">%s</xliff:g>. Bạn chỉ có thể truy cập Internet thông qua Wi-Fi."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"nhà mạng của bạn"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Vì ứng dụng đang che khuất yêu cầu cấp quyền nên Cài đặt không thể xác minh câu trả lời của bạn."</string>
<string name="slice_permission_title" msgid="7465009437851044444">"Cho phép <xliff:g id="APP_0">%1$s</xliff:g> hiển thị các lát của <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Mở <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Tùy chọn cài đặt cho bong bóng <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Bạn muốn cho phép bong bóng của <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Quản lý"</string>
<string name="no_bubbles" msgid="337101288173078247">"Từ chối"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Cho phép"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Hỏi tôi sau"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Chuyển lên trên cùng bên phải"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Chuyển tới dưới cùng bên trái"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Chuyển tới dưới cùng bên phải"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index a40395f..5f1b4ad 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"在<xliff:g id="TIME">%s</xliff:g> 开启"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"直到<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"深色主题背景"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC 已停用"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC 已启用"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"不再显示"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"全部清除"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"管理"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"无声通知"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"清除所有无声通知"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"勿扰模式暂停的通知"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"立即开始"</string>
<string name="empty_shade_text" msgid="708135716272867002">"没有通知"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"已固定屏幕"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“返回”和“概览”即可取消固定屏幕。"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“返回”和“主屏幕”即可取消固定屏幕。"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"这会使此屏幕固定显示,直到您取消固定为止。向上滑动并按住即可取消固定。"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“概览”即可取消固定屏幕。"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“主屏幕”即可取消固定屏幕。"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"要取消固定此屏幕,请触摸并按住“返回”和“概览”按钮"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"要继续显示来自此应用的通知吗?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"无声通知"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"已设为优先"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"一律静音。显示在下拉通知栏中。"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"一律静音。显示在下拉通知栏和状态栏中。"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"一律静音。显示在下拉通知栏和锁定屏幕中。"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"一律静音。显示在下拉通知栏、状态栏以及锁定屏幕中。"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"发出提示音,并显示在下拉通知栏、状态栏以及锁定屏幕中。"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"只会在下拉通知栏中显示通知,引起您的注意。一律不发出提示音。"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"显示在优先通知下方。一律不发出提示音。"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"显示在优先通知下方。一律不发出提示音。"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"显示在优先通知下方。一律不发出提示音。"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"通过提示音和状态栏图标吸引您的注意。这类通知会显示在锁定屏幕上。"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"无法修改这些通知。"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"您无法在此处配置这组通知"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"代理通知"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"此应用正在使用摄像头。"</string>
<string name="appops_microphone" msgid="741508267659494555">"此应用正在使用麦克风。"</string>
@@ -880,7 +888,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"在后台运行的应用"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"点按即可详细了解电量和流量消耗情况"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"要关闭移动数据网络吗?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"您将无法通过<xliff:g id="CARRIER">%s</xliff:g>获取移动数据访问权限或连接到互联网。您只能通过 WLAN 连接到互联网。"</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"您将无法通过<xliff:g id="CARRIER">%s</xliff:g>使用移动数据或互联网,只能通过 WLAN 连接到互联网。"</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"您的运营商"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"由于某个应用遮挡了权限请求界面,因此“设置”应用无法验证您的回应。"</string>
<string name="slice_permission_title" msgid="7465009437851044444">"要允许“<xliff:g id="APP_0">%1$s</xliff:g>”显示“<xliff:g id="APP_2">%2$s</xliff:g>”图块吗?"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"打开<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"<xliff:g id="APP_NAME">%1$s</xliff:g>气泡的相关设置"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"要允许来自<xliff:g id="APP_NAME">%1$s</xliff:g>的气泡吗?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"管理"</string>
<string name="no_bubbles" msgid="337101288173078247">"拒绝"</string>
<string name="yes_bubbles" msgid="668809525728633841">"允许"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"以后再说"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"移至右上角"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"移至左下角"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"移至右下角"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index aaba9c7..b3e48ae 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -67,7 +67,7 @@
<string name="usb_disable_contaminant_detection" msgid="2103905315747120033">"啟用 USB"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string>
- <string name="global_action_screenshot" msgid="8329831278085426283">"擷取螢幕畫面"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"螢幕截圖"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在儲存螢幕擷取畫面..."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"正在儲存螢幕擷取畫面..."</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"螢幕擷取畫面已儲存"</string>
@@ -313,7 +313,7 @@
<string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"直向"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"橫向"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"輸入法"</string>
- <string name="quick_settings_location_label" msgid="5011327048748762257">"定位"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"位置"</string>
<string name="quick_settings_location_off_label" msgid="7464544086507331459">"位置資訊已關閉"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"媒體裝置"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
@@ -354,7 +354,7 @@
<item quantity="one">%d 部裝置</item>
</plurals>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
- <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"閃光燈"</string>
+ <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"電筒"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"流動數據"</string>
<string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"數據用量"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"剩餘資料"</string>
@@ -366,9 +366,11 @@
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"夜燈模式"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"在日落時開啟"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"在日出時關閉"</string>
- <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"在<xliff:g id="TIME">%s</xliff:g>開啟"</string>
- <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"在<xliff:g id="TIME">%s</xliff:g>關閉"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> 開啟"</string>
+ <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"直到<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"深色主題背景"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC 已停用"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC 已啟用"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"不用再顯示"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"全部清除"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"管理"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"低重要性通知"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"清除所有低重要性通知"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"「請勿騷擾」模式已將通知暫停"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"立即開始"</string>
<string name="empty_shade_text" msgid="708135716272867002">"沒有通知"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"螢幕已固定"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"畫面將會繼續顯示,直至您取消固定。按住 [返回] 和 [概覽] 即可取消固定。"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"畫面將會繼續顯示,直至您取消固定為止。按住 [返回] 按鈕和主按鈕即可取消固定。"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"畫面將會繼續顯示,直至您取消固定為止。向上滑動並按住即可取消固定。"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"畫面將會繼續顯示,直至您取消固定。按住 [概覽] 即可取消固定。"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"畫面將會繼續顯示,直至您取消固定為止。按住主按鈕即可取消固定。"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"如要取消固定此畫面,請按住 [返回] 按鈕和 [概覽] 按鈕"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"要繼續顯示此應用程式的通知嗎?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"低重要性"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"優先"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"一律靜音。在下拉式通知欄中顯示。"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"一律靜音。在下拉式通知欄和狀態列中顯示。"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"一律靜音。在下拉式通知欄和上鎖畫面中顯示。"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"一律靜音。在下拉式通知欄、狀態列和上鎖畫面中顯示。"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"發出音效,並在下拉式通知欄、狀態列和上鎖畫面中顯示。"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"協助您只查看下拉式通知欄中的通知。一律靜音。"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"顯示不重要的通知。一律靜音。"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"顯示不重要的通知。一律靜音。"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"顯示不重要的通知。一律靜音。"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"透過聲音和狀態列圖示引起您的注意,並在上鎖畫面顯示。"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"無法修改這些通知。"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"無法在此設定這組通知"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"代理通知"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"此應用程式目前使用相機。"</string>
<string name="appops_microphone" msgid="741508267659494555">"此應用程式目前使用麥克風。"</string>
@@ -880,7 +888,7 @@
<string name="running_foreground_services_title" msgid="381024150898615683">"正在背景中執行的應用程式"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"輕按即可查看電池和數據用量詳情"</string>
<string name="mobile_data_disable_title" msgid="1068272097382942231">"要關閉流動數據嗎?"</string>
- <string name="mobile_data_disable_message" msgid="4756541658791493506">"您將無法透過 <xliff:g id="CARRIER">%s</xliff:g> 存取流動數據或互聯網。您必須連接 Wi-Fi 才能使用互聯網。"</string>
+ <string name="mobile_data_disable_message" msgid="4756541658791493506">"您將無法透過「<xliff:g id="CARRIER">%s</xliff:g>」存取流動數據或互聯網。必須連接 Wi-Fi 才能使用互聯網。"</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"您的流動網絡供應商"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"由於某個應用程式已阻擋權限要求畫面,因此「設定」應用程式無法驗證您的回應。"</string>
<string name="slice_permission_title" msgid="7465009437851044444">"要允許「<xliff:g id="APP_0">%1$s</xliff:g>」顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的快訊嗎?"</string>
@@ -896,7 +904,7 @@
<string name="auto_saver_enabled_text" msgid="874711029884777579">"省電模式將會在電量低於 <xliff:g id="PERCENTAGE">%d</xliff:g>%% 時自動開啟。"</string>
<string name="open_saver_setting_action" msgid="8314624730997322529">"設定"</string>
<string name="auto_saver_okay_action" msgid="2701221740227683650">"知道了"</string>
- <string name="heap_dump_tile_name" msgid="9141031328971226374">"傾印 SysUI 記憶體快照"</string>
+ <string name="heap_dump_tile_name" msgid="9141031328971226374">"轉儲 SysUI 堆"</string>
<string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"「<xliff:g id="APP">%1$s</xliff:g>」正在使用<xliff:g id="TYPES_LIST">%2$s</xliff:g>。"</string>
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"有多個應用程式正在使用<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">"、 "</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"開啟「<xliff:g id="APP_NAME">%1$s</xliff:g>」"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」小視窗設定"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"要允許開啟「<xliff:g id="APP_NAME">%1$s</xliff:g>」的小視窗嗎?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"管理"</string>
<string name="no_bubbles" msgid="337101288173078247">"拒絕"</string>
<string name="yes_bubbles" msgid="668809525728633841">"允許"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"稍後再詢問我"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"移去右上角"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"移去左下角"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"移去右下角"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 51209d2..46d2285 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> 開啟"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> 關閉"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"深色主題"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC 已停用"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC 已啟用"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"不要再顯示"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"全部清除"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"管理"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"無聲通知"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"清除所有無聲通知"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"「零打擾」模式已將通知設為暫停"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"立即開始"</string>
<string name="empty_shade_text" msgid="708135716272867002">"沒有通知"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"螢幕已固定"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"這會讓目前的螢幕畫面保持顯示狀態,直到取消固定為止。按住 [返回] 按鈕和 [總覽] 按鈕即可取消固定。"</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"這會讓應用程式顯示在螢幕上,直到取消固定為止。按住 [返回] 按鈕和主螢幕按鈕即可取消固定。"</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"這會讓目前的螢幕畫面保持顯示狀態,直到取消固定為止。向上滑動並按住即可取消固定。"</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"這會讓目前的螢幕畫面保持顯示狀態,直到取消固定為止。按住 [總覽] 按鈕即可取消固定。"</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"這會讓應用程式顯示在螢幕上,直到取消固定為止。按住主螢幕按鈕即可取消固定。"</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"如要取消固定這個螢幕畫面,請按住「返回」按鈕和「總覽」按鈕"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"要繼續顯示這個應用程式的通知嗎?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"無聲通知"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"已設為優先"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"一律不發出音效,但會顯示在下拉式通知欄中。"</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"一律不發出音效,但會顯示在下拉式通知欄和狀態列中。"</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"一律不發出音效,但會顯示在下拉式通知欄和螢幕鎖定畫面中。"</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"一律不發出音效,但會顯示在下拉式通知欄、狀態列和螢幕鎖定畫面中。"</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"會發出音效並顯示在下拉式通知欄、狀態列和螢幕鎖定畫面中。"</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"只會在下拉式通知欄中顯示通知,且一律不發出音效。"</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"顯示在優先通知下方,且一律不發出音效。"</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"顯示在優先通知下方,且一律不發出音效。"</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"顯示在優先通知下方,且一律不發出音效。"</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"發出音效並顯示「狀態列」圖示吸引你的注意力。這類通知會顯示在螢幕鎖定畫面上。"</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"無法修改這些通知。"</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"無法在這裡設定這個通知群組"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"經過 Proxy 處理的通知"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"這個應用程式正在使用相機。"</string>
<string name="appops_microphone" msgid="741508267659494555">"這個應用程式正在使用麥克風。"</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"開啟「<xliff:g id="APP_NAME">%1$s</xliff:g>」"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」泡泡的設定"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」顯示泡泡嗎?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"管理"</string>
<string name="no_bubbles" msgid="337101288173078247">"拒絕"</string>
<string name="yes_bubbles" msgid="668809525728633841">"允許"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"稍後再詢問我"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"移至右上方"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"移至左下方"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"移至右下方"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 611d827..066e159 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -369,6 +369,8 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Kuvulwe ngo-<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Kuze kube ngu-<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="512534812963862137">"Itimu emnyama"</string>
+ <!-- no translation found for quick_settings_ui_mode_night_label_battery_saver (3496696903886673256) -->
+ <skip />
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"I-NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"I-NFC ikhutshaziwe"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"I-NFC inikwe amandla"</string>
@@ -448,6 +450,8 @@
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ungabonisi futhi"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Sula konke"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Phatha"</string>
+ <string name="notification_section_header_gentle" msgid="8356064473678167305">"Izaziso ezimnene"</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4270384919249494640">"Sula zonke izaziso ezimnene"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Izaziso zimiswe okwesikhashana ukungaphazamisi"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Qala manje"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Azikho izaziso"</string>
@@ -527,6 +531,7 @@
<string name="screen_pinning_title" msgid="3273740381976175811">"Isikrini siphiniwe"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Lokhu kuyigcina ibukeka uze ususe ukuphina. Thinta uphinde ubambe okuthi Emuva Nokubuka konke ukuze ususe ukuphina."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Lokhu kuyigcina ibonakala uze uyisuse. Thinta uphinde ubambe okuthi Emuva nokuthi Ekhaya ukuze ususe ukuphina."</string>
+ <string name="screen_pinning_description_gestural" msgid="1191513974909607884">"Lokhu kuyigcina ibonakala uze ususe ukuphina. Swayiphela phezulu uphinde ubambe ukuze ususe ukuphina."</string>
<string name="screen_pinning_description_accessible" msgid="426190689254018656">"Lokhu kuyigcina ibukeka uze ususe ukuphina. Thinta uphinde ubambe Ukubuka konke ukuze ususe ukuphina."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Lokhu kuyigcina ibukeka uze ususe ukuphina. Thinta uphinde ubambe okuthi Ekhaya ukuze ususe ukuphina."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Ukuze ususe ukuphina lesi sikrini, thinta uphinde ubambe izinkinobho zokubuyela emuva nezokubuka konke"</string>
@@ -638,14 +643,17 @@
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Qhubeka nokubonisa izaziso kusuka kulolu hlelo lokusebenza?"</string>
<string name="notification_silence_title" msgid="7352089096356977930">"Okumnene"</string>
<string name="notification_alert_title" msgid="3966526305405016221">"Okwenziwe kwabaluleka"</string>
- <string name="notification_channel_summary_low" msgid="8816251796432620434">"Ihlala ithulile. Ibonisa umthunzi wokudonsela phansi."</string>
- <string name="notification_channel_summary_low_status" msgid="838359173060008373">"Ihlala ithulile. Iboniswa kumthunzi wokudonselwa phansi nakubha yesimo."</string>
- <string name="notification_channel_summary_low_lock" msgid="1568361562011497978">"Ihlala ithulile. Iboniswa kumthunzi wokudonsela phansi nowokukhiywa kwesikrini."</string>
- <string name="notification_channel_summary_low_status_lock" msgid="966512668777695595">"Ihlala ithulile. Iboniswa kumthunzi wokudonselwa phansi, ibha yesimo nokukhiywa kwesikrini."</string>
- <string name="notification_channel_summary_default" msgid="619096010741301745">"Yenza umsindo futhi iboniswa kumthunzi wokudonsela phansi, ibha yesimo nasekukhiyweni kwesikrini."</string>
+ <string name="notification_channel_summary_low" msgid="1065819618107531284">"Ikusiza ukuthi ugxile ngezaziso kuphela kumthunzi wokudonsela phansi. Ihlala ithulile."</string>
+ <string name="notification_channel_summary_low_status" msgid="2702170424808743755">"Ibonisa izaziso ezibalulekile ezingezansi. Ihlala ithulile."</string>
+ <string name="notification_channel_summary_low_lock" msgid="7966605244472624458">"Ibonisa izaziso ezibalulekile ezingezansi. Ihlala ithulile."</string>
+ <string name="notification_channel_summary_low_status_lock" msgid="7012562768950012739">"Ibonisa izaziso ezibalulekile ezingezansi. Ihlala ithulile."</string>
+ <string name="notification_channel_summary_default" msgid="3847289783382316019">"Yenza uyinake ngomsindo nesithonjana sebha yesimo. Iboniswa kusikrini sokukhiya."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Lezi zaziso azikwazi ukushintshwa."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Leli qembu lezaziso alikwazi ukulungiselelwa lapha"</string>
- <!-- no translation found for notification_delegate_header (2857691673814814270) -->
+ <string name="notification_delegate_header" msgid="2857691673814814270">"Isaziso sommeli"</string>
+ <!-- no translation found for notification_channel_dialog_title (5745335243729167866) -->
+ <skip />
+ <!-- no translation found for see_more_title (5358726697042112726) -->
<skip />
<string name="appops_camera" msgid="8100147441602585776">"Lolu hlelo lokusebenza lusebenzisa ikhamera."</string>
<string name="appops_microphone" msgid="741508267659494555">"Lolu hlelo lokusebenza lusebenzisa imakrofoni."</string>
@@ -911,6 +919,7 @@
<string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Vula i-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_settings_button_description" msgid="2970630476657287189">"Izilungiselelo zamabhamuza e-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubbles_prompt" msgid="8807968030159469710">"Vumela amabhamuza kusukela ku-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="manage_bubbles_text" msgid="7027739766859191408">"Phatha"</string>
<string name="no_bubbles" msgid="337101288173078247">"Yenqaba"</string>
<string name="yes_bubbles" msgid="668809525728633841">"Vumela"</string>
<string name="ask_me_later_bubbles" msgid="2147688438402939029">"Ngibuze ngesinye isikhathi"</string>
@@ -921,4 +930,6 @@
<string name="bubble_accessibility_action_move_top_right" msgid="1671844272347036806">"Hambisa phezulu ngakwesokudla"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="206369104473183217">"Hambisa inkinobho ngakwesokunxele"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="8705660152384312329">"Hambisa inkinobho ngakwesokudla"</string>
+ <!-- no translation found for bubble_dismiss_text (8028337712674081668) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 4e1a7d0..6d7e205 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -95,6 +95,11 @@
<color name="notification_guts_header_text_color">@color/GM2_grey_900</color>
<color name="notification_silence_color">#FF32c1de</color>
<color name="notification_alert_color">#FFF87B2B</color>
+ <color name="notification_guts_button_color">@color/GM2_blue_700</color>
+
+ <color name="notification_section_header_label_color">@color/GM2_grey_900</color>
+ <!-- The divider view for the notification channel editor half-shelf -->
+ <color name="notification_channel_dialog_separator">@color/GM2_grey_200</color>
<color name="assist_orb_color">#ffffff</color>
@@ -110,11 +115,9 @@
<color name="segmented_buttons_background">#14FFFFFF</color><!-- 8% white -->
- <color name="dark_mode_icon_color_single_tone">#99000000</color>
<color name="dark_mode_icon_color_dual_tone_background">#3d000000</color>
<color name="dark_mode_icon_color_dual_tone_fill">#7a000000</color>
- <color name="light_mode_icon_color_single_tone">#ffffff</color>
<color name="light_mode_icon_color_dual_tone_background">#4dffffff</color>
<color name="light_mode_icon_color_dual_tone_fill">#ffffff</color>
@@ -156,7 +159,9 @@
<!-- Biometric dialog colors -->
<color name="biometric_dialog_dim_color">#80000000</color> <!-- 50% black -->
- <color name="biometric_face_icon_gray">#ffbdc1c6</color>
+ <color name="biometric_dialog_gray">#ff757575</color>
+ <color name="biometric_dialog_accent">#ff008577</color> <!-- dark teal -->
+ <color name="biometric_dialog_error">#ffd93025</color> <!-- red 600 -->
<!-- Logout button -->
<color name="logout_button_bg_color">#ccffffff</color>
@@ -177,6 +182,9 @@
<color name="GM2_red_300">#F28B82</color>
<color name="GM2_red_500">#B71C1C</color>
+ <color name="GM2_blue_200">#AECBFA</color>
+ <color name="GM2_blue_700">#1967D2</color>
+
<color name="GM2_yellow_500">#FFFBBC04</color>
<color name="GM2_green_500">#FF34A853</color>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 4abe9f0..d774c55 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -331,7 +331,7 @@
<!-- Nav bar button default ordering/layout -->
<string name="config_navBarLayout" translatable="false">left[.5W],back[1WC];home;recent[1WC],right[.5W]</string>
<string name="config_navBarLayoutQuickstep" translatable="false">back[1.7WC];home;contextual[1.7WC]</string>
- <string name="config_navBarLayoutHandle" translatable="false">start_contextual[.1WC];home_handle;ime_switcher[.1WC]</string>
+ <string name="config_navBarLayoutHandle" translatable="false">start_contextual[40AC];home_handle;ime_switcher[40AC]</string>
<bool name="quick_settings_show_full_alarm">false</bool>
@@ -494,4 +494,7 @@
<!-- Launcher package name for overlaying icons. -->
<string name="launcher_overlayable_package" translatable="false">com.android.launcher3</string>
+ <!-- ThemePicker package name for overlaying icons. -->
+ <string name="themepicker_overlayable_package" translatable="false">com.android.wallpaper</string>
+
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ce958ab..6297423 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -60,6 +60,9 @@
<!-- Height of notification icons in the status bar -->
<dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
+ <!-- Default horizontal drawable padding for status bar icons. -->
+ <dimen name="status_bar_horizontal_padding">2.5dp</dimen>
+
<!-- Height of the battery icon in the status bar. -->
<dimen name="status_bar_battery_icon_height">13.0dp</dimen>
@@ -249,6 +252,9 @@
<!-- size at which Notification icons will be drawn on Ambient Display -->
<dimen name="status_bar_icon_drawing_size_dark">@*android:dimen/notification_header_icon_size_ambient</dimen>
+ <!-- size of notification icons on AOD -->
+ <dimen name="dark_shelf_icon_size">16dp</dimen>
+
<!-- opacity at which Notification icons will be drawn in the status bar -->
<item type="dimen" name="status_bar_icon_drawing_alpha">90%</item>
@@ -591,6 +597,8 @@
<dimen name="keyguard_clock_notifications_margin">30dp</dimen>
<!-- Minimum margin between clock and status bar -->
<dimen name="keyguard_clock_top_margin">36dp</dimen>
+ <!-- The margin between top of clock and bottom of lock icon. -->
+ <dimen name="keyguard_clock_lock_margin">16dp</dimen>
<item name="scrim_behind_alpha" format="float" type="dimen">0.62</item>
@@ -690,6 +698,9 @@
<!-- The top padding of the clear all button -->
<dimen name="clear_all_padding_top">12dp</dimen>
+ <dimen name="notification_section_header_height">40dp</dimen>
+ <dimen name="notification_section_header_padding_left">16dp</dimen>
+
<!-- Largest size an avatar might need to be drawn in the user picker, status bar, or
quick settings header -->
<dimen name="max_avatar_size">48dp</dimen>
@@ -741,7 +752,7 @@
<dimen name="keyguard_lock_width">42dp</dimen>
<dimen name="keyguard_lock_padding">20dp</dimen>
- <dimen name="keyguard_indication_margin_bottom">44dp</dimen>
+ <dimen name="keyguard_indication_margin_bottom">40dp</dimen>
<!-- The text size for battery level -->
<dimen name="battery_level_text_size">12sp</dimen>
@@ -1087,6 +1098,8 @@
<dimen name="bubble_padding">8dp</dimen>
<!-- Size of individual bubbles. -->
<dimen name="individual_bubble_size">52dp</dimen>
+ <!-- Size of the circle around the bubbles when they're in the dismiss target. -->
+ <dimen name="bubble_dismiss_encircle_size">56dp</dimen>
<!-- How much to inset the icon in the circle -->
<dimen name="bubble_icon_inset">16dp</dimen>
<!-- Padding around the view displayed when the bubble is expanded -->
@@ -1121,13 +1134,14 @@
<dimen name="bubble_stack_starting_offset_y">100dp</dimen>
<!-- Size of image buttons in the bubble header -->
<dimen name="bubble_header_icon_size">48dp</dimen>
- <!-- Size of the app icon shown in the bubble permission view -->
- <dimen name="bubble_permission_icon_size">24dp</dimen>
<!-- Space between the pointer triangle and the bubble expanded view -->
<dimen name="bubble_pointer_margin">8dp</dimen>
<!-- Height of the permission prompt shown with bubbles -->
<dimen name="bubble_permission_height">120dp</dimen>
-
+ <!-- Padding applied to the bubble dismiss target. Touches in this padding cause the bubbles to
+ snap to the dismiss target. -->
+ <dimen name="bubble_dismiss_target_padding_x">40dp</dimen>
+ <dimen name="bubble_dismiss_target_padding_y">20dp</dimen>
<!-- Size of the RAT type for CellularTile -->
<dimen name="celltile_rat_type_size">10sp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 501b1b5..e97055f0 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -103,11 +103,19 @@
<item type="id" name="action_snooze_assistant_suggestion_1"/>
<item type="id" name="action_snooze"/>
+ <!-- Accessibility actions for bubbles. -->
+ <item type="id" name="action_move_top_left"/>
+ <item type="id" name="action_move_top_right"/>
+ <item type="id" name="action_move_bottom_left"/>
+ <item type="id" name="action_move_bottom_right"/>
+
<!-- For StatusIconContainer to tag its icon views -->
<item type="id" name="status_bar_view_state_tag" />
<item type="id" name="display_cutout" />
+ <item type="id" name="row_tag_for_content_view" />
+
<!-- Optional cancel button on Keyguard -->
<item type="id" name="cancel_button"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index dc35653..e01e6a8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -288,8 +288,18 @@
<!-- Message shown when a biometric is authenticated, asking the user to confirm authentication [CHAR LIMIT=30] -->
<string name="biometric_dialog_confirm">Confirm</string>
- <!-- Button name on BiometricPrompt shown when a biometric is detected but not authenticated. Tapping the button resumes authentication [CHAR_LIMIT=30] -->
+ <!-- Button name on BiometricPrompt shown when a biometric is detected but not authenticated. Tapping the button resumes authentication [CHAR LIMIT=30] -->
<string name="biometric_dialog_try_again">Try again</string>
+ <!-- Content description for empty spaces that are not taken by the biometric dialog. Clicking on these areas will cancel authentication and dismiss the biometric dialog [CHAR LIMIT=NONE] -->
+ <string name="biometric_dialog_empty_space_description">Empty region, tap to cancel authentication</string>
+ <!-- Content description for the face icon when the device is not authenticating anymore [CHAR LIMIT=NONE] -->
+ <string name="biometric_dialog_face_icon_description_idle">Please try again</string>
+ <!-- Content description for the face icon when the device is authenticating [CHAR LIMIT=NONE] -->
+ <string name="biometric_dialog_face_icon_description_authenticating">Looking for your face</string>
+ <!-- Content description for the face icon when the user has been authenticated [CHAR LIMIT=NONE] -->
+ <string name="biometric_dialog_face_icon_description_authenticated">Face authenticated</string>
+ <!-- Content description for the face icon when the user has been authenticated and the confirm button has been pressed [CHAR LIMIT=NONE] -->
+ <string name="biometric_dialog_face_icon_description_confirmed">Confirmed</string>
<!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication -->
<string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
@@ -871,6 +881,8 @@
<string name="quick_settings_secondary_label_until">Until <xliff:g id="time" example="7 am">%s</xliff:g></string>
<!-- QuickSettings: Label for the toggle to activate Dark theme (A.K.A Dark Mode). [CHAR LIMIT=20] -->
<string name="quick_settings_ui_mode_night_label">Dark Theme</string>
+ <!-- QuickSettings: Label for the Dark theme tile when enabled by battery saver. [CHAR LIMIT=40] -->
+ <string name="quick_settings_ui_mode_night_label_battery_saver">Dark Theme\nBattery saver</string>
<!-- QuickSettings: NFC tile [CHAR LIMIT=NONE] -->
<string name="quick_settings_nfc_label">NFC</string>
@@ -1102,6 +1114,12 @@
<!-- The text for the manage notifications link. [CHAR LIMIT=40] -->
<string name="manage_notifications_text">Manage</string>
+ <!-- Section title for notifications that do not vibrate or make noise. [CHAR LIMIT=40] -->
+ <string name="notification_section_header_gentle">Gentle notifications</string>
+
+ <!-- Content description for accessibility: Tapping this button will dismiss all gentle notifications [CHAR LIMIT=NONE] -->
+ <string name="accessibility_notification_section_header_gentle_clear_all">Clear all gentle notifications</string>
+
<!-- The text to show in the notifications shade when dnd is suppressing notifications. [CHAR LIMIT=100] -->
<string name="dnd_suppressing_shade_text">Notifications paused by Do Not Disturb</string>
@@ -1682,6 +1700,12 @@
<!-- Notification: Control panel: Label for the app that posted this notification, if it's not the package that the notification was posted for -->
<string name="notification_delegate_header">Proxied notification</string>
+ <!-- [CHAR LIMIT=40 Notification: Label for the inline channel blocking view -->
+ <string name="notification_channel_dialog_title">All <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> notifications</string>
+
+ <!-- [CHAR LIMIT=20 Notification: "See more" button -->
+ <string name="see_more_title">See more</string>
+
<!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
<string name="appops_camera">This app is using the camera.</string>
<!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
@@ -2436,4 +2460,6 @@
<string name="bubble_accessibility_action_move_bottom_left">Move bottom left</string>
<!-- Action in accessibility menu to move the stack of bubbles to the bottom right of the screen. [CHAR LIMIT=30]-->
<string name="bubble_accessibility_action_move_bottom_right">Move bottom right</string>
+ <!-- Text used for the bubble dismiss area. Bubbles dragged to, or flung towards, this area will go away. [CHAR LIMIT=20] -->
+ <string name="bubble_dismiss_text">Dismiss</string>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 23de2ac..59ed5ce 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -285,6 +285,7 @@
<item name="*android:lockPatternStyle">@style/LockPatternStyle</item>
<item name="passwordStyle">@style/PasswordTheme</item>
<item name="backgroundProtectedStyle">@style/BackgroundProtectedStyle</item>
+ <item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
<!-- Needed for MediaRoute chooser dialog -->
<item name="*android:isLightTheme">false</item>
@@ -311,7 +312,7 @@
<item name="*android:errorColor">?android:attr/colorError</item>
</style>
- <style name="qs_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+ <style name="qs_theme" parent="@style/Theme.SystemUI">
<item name="lightIconTheme">@style/QSIconTheme</item>
<item name="darkIconTheme">@style/QSIconTheme</item>
<item name="android:colorError">@*android:color/error_color_material_dark</item>
@@ -348,7 +349,7 @@
<style name="AutoSizingList">
<item name="enableAutoSizing">true</item>
</style>
- <style name="Theme.MediaProjectionAlertDialog" parent="android:Theme.DeviceDefault">
+ <style name="Theme.SystemUI.MediaProjectionAlertDialog">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
@@ -449,10 +450,16 @@
<item name="android:alpha">0.54</item>
</style>
+ <style name="TextAppearance.NotificationInfo.Title">
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:textColor">@color/notification_primary_text_color</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+
<style name="TextAppearance.NotificationInfo.Button">
<item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
<item name="android:textSize">16sp</item>
- <item name="android:textColor">?android:attr/colorAccent</item>
+ <item name="android:textColor">@color/notification_guts_button_color</item>
<item name="android:background">@drawable/btn_borderless_rect</item>
<item name="android:gravity">center_vertical</item>
<item name="android:focusable">true</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
index 40d98c1..f384507 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
@@ -151,19 +151,34 @@
return plugins.size() != 0;
}
- private void disable(PluginInfo info,
- @PluginEnabler.DisableReason int reason) {
+ private boolean isPluginWhitelisted(ComponentName pluginName) {
+ for (String componentNameOrPackage : mWhitelistedPlugins) {
+ ComponentName componentName = ComponentName.unflattenFromString(componentNameOrPackage);
+ if (componentName == null) {
+ if (componentNameOrPackage.equals(pluginName.getPackageName())) {
+ return true;
+ }
+ } else {
+ if (componentName.equals(pluginName)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void disable(PluginInfo info, @PluginEnabler.DisableReason int reason) {
// Live by the sword, die by the sword.
// Misbehaving plugins get disabled and won't come back until uninstall/reinstall.
+ ComponentName pluginComponent = new ComponentName(info.mPackage, info.mClass);
// If a plugin is detected in the stack of a crash then this will be called for that
// plugin, if the plugin causing a crash cannot be identified, they are all disabled
// assuming one of them must be bad.
- if (mWhitelistedPlugins.contains(info.mPackage)) {
+ if (isPluginWhitelisted(pluginComponent)) {
// Don't disable whitelisted plugins as they are a part of the OS.
return;
}
- ComponentName pluginComponent = new ComponentName(info.mPackage, info.mClass);
Log.w(TAG, "Disabling plugin " + pluginComponent.flattenToShortString());
mManager.getPluginEnabler().setDisabled(pluginComponent, reason);
}
@@ -288,6 +303,13 @@
if (result.size() > 1 && !mAllowMultiple) {
// TODO: Show warning.
Log.w(TAG, "Multiple plugins found for " + mAction);
+ if (DEBUG) {
+ for (ResolveInfo info : result) {
+ ComponentName name = new ComponentName(info.serviceInfo.packageName,
+ info.serviceInfo.name);
+ Log.w(TAG, " " + name);
+ }
+ }
return;
}
for (ResolveInfo info : result) {
@@ -305,7 +327,7 @@
protected PluginInfo<T> handleLoadPlugin(ComponentName component) {
// This was already checked, but do it again here to make extra extra sure, we don't
// use these on production builds.
- if (!isDebuggable && !mWhitelistedPlugins.contains(component.getPackageName())) {
+ if (!isDebuggable && !isPluginWhitelisted(component)) {
// Never ever ever allow these on production builds, they are only for prototyping.
Log.w(TAG, "Plugin cannot be loaded on production build: " + component);
return null;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
index 7558efa..5b9ee1c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
@@ -16,6 +16,8 @@
package com.android.systemui.shared.recents.model;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
import android.content.ComponentName;
@@ -62,6 +64,12 @@
@ViewDebug.ExportedProperty(category="recents")
public long lastActiveTime;
+ /**
+ * The id of the task was running from which display.
+ */
+ @ViewDebug.ExportedProperty(category = "recents")
+ public final int displayId;
+
// The source component name which started this task
public final ComponentName sourceComponent;
@@ -79,6 +87,7 @@
this.sourceComponent = sourceComponent;
this.userId = t.userId;
this.lastActiveTime = t.lastActiveTime;
+ this.displayId = t.displayId;
updateHashCode();
}
@@ -90,6 +99,19 @@
this.sourceComponent = sourceComponent;
this.userId = userId;
this.lastActiveTime = lastActiveTime;
+ this.displayId = DEFAULT_DISPLAY;
+ updateHashCode();
+ }
+
+ public TaskKey(int id, int windowingMode, Intent intent,
+ ComponentName sourceComponent, int userId, long lastActiveTime, int displayId) {
+ this.id = id;
+ this.windowingMode = windowingMode;
+ this.baseIntent = intent;
+ this.sourceComponent = sourceComponent;
+ this.userId = userId;
+ this.lastActiveTime = lastActiveTime;
+ this.displayId = displayId;
updateHashCode();
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index f2a961d..21b3a00 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -76,6 +76,8 @@
public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { }
public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) { }
+ public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { }
+
/**
* Checks that the current user matches the process. Since
* {@link android.app.ITaskStackListener} is not multi-user aware, handlers of
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 6e3eb7c..06ae399 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -70,6 +70,15 @@
public void removeListener(TaskStackChangeListener listener) {
mTaskStackListeners.remove(listener);
+ if (mTaskStackListeners.isEmpty() && mRegistered) {
+ // Unregister mTaskStackListener once we have no more listeners
+ try {
+ ActivityTaskManager.getService().unregisterTaskStackListener(this);
+ mRegistered = false;
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to call unregisterTaskStackListener", e);
+ }
+ }
}
@Override
@@ -175,6 +184,11 @@
}
@Override
+ public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) throws RemoteException {
+ mHandler.obtainMessage(H.ON_BACK_PRESSED_ON_TASK_ROOT, taskInfo).sendToTarget();
+ }
+
+ @Override
public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation)
throws RemoteException {
mHandler.obtainMessage(H.ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE, taskId,
@@ -205,6 +219,7 @@
private static final int ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE = 15;
private static final int ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED = 16;
private static final int ON_SIZE_COMPAT_MODE_ACTIVITY_CHANGED = 17;
+ private static final int ON_BACK_PRESSED_ON_TASK_ROOT = 18;
public H(Looper looper) {
@@ -334,6 +349,13 @@
}
break;
}
+ case ON_BACK_PRESSED_ON_TASK_ROOT: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onBackPressedOnTaskRoot(
+ (RunningTaskInfo) msg.obj);
+ }
+ break;
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 12d1f7c..2090748 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -174,6 +174,9 @@
mSimSlotsNumber = ((TelephonyManager) context.getSystemService(
Context.TELEPHONY_SERVICE)).getPhoneCount();
mSimErrorState = new boolean[mSimSlotsNumber];
+ updateDisplayOpportunisticSubscriptionCarrierText(SystemProperties.getBoolean(
+ TelephonyProperties.DISPLAY_OPPORTUNISTIC_SUBSCRIPTION_CARRIER_TEXT_PROPERTY_NAME,
+ false));
}
/**
@@ -282,10 +285,8 @@
*
*/
@VisibleForTesting
- public void updateDisplayOpportunisticSubscriptionCarrierText() {
- mDisplayOpportunisticSubscriptionCarrierText = SystemProperties
- .getBoolean(TelephonyProperties
- .DISPLAY_OPPORTUNISTIC_SUBSCRIPTION_CARRIER_TEXT_PROPERTY_NAME, false);
+ public void updateDisplayOpportunisticSubscriptionCarrierText(boolean isEnable) {
+ mDisplayOpportunisticSubscriptionCarrierText = isEnable;
}
protected List<SubscriptionInfo> getSubscriptionInfo() {
@@ -480,13 +481,13 @@
break;
case SimLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
+ carrierText = makeCarrierStringOnLocked(
getContext().getText(R.string.keyguard_sim_locked_message),
text);
break;
case SimPukLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
+ carrierText = makeCarrierStringOnLocked(
getContext().getText(R.string.keyguard_sim_puk_locked_message),
text);
break;
@@ -514,6 +515,26 @@
return simMessage;
}
+ /*
+ * Add "SIM card is locked" in parenthesis after carrier name, so it is easily associated in
+ * DSDS
+ */
+ private CharSequence makeCarrierStringOnLocked(CharSequence simMessage,
+ CharSequence carrierName) {
+ final boolean simMessageValid = !TextUtils.isEmpty(simMessage);
+ final boolean carrierNameValid = !TextUtils.isEmpty(carrierName);
+ if (simMessageValid && carrierNameValid) {
+ return mContext.getString(R.string.keyguard_carrier_name_with_sim_locked_template,
+ carrierName, simMessage);
+ } else if (simMessageValid) {
+ return simMessage;
+ } else if (carrierNameValid) {
+ return carrierName;
+ } else {
+ return "";
+ }
+ }
+
/**
* Determine the current status of the lock screen given the SIM state and other stuff.
*/
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 8d62bca..d0b2c58 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -3,22 +3,20 @@
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import android.animation.Animator;
-import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Build;
-import android.transition.ChangeBounds;
import android.transition.Transition;
import android.transition.TransitionListenerAdapter;
import android.transition.TransitionManager;
+import android.transition.TransitionSet;
import android.transition.TransitionValues;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
-import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -52,6 +50,11 @@
private static final String TAG = "KeyguardClockSwitch";
/**
+ * Animation fraction when text is transitioned to/from bold.
+ */
+ private static final float TO_BOLD_TRANSITION_FRACTION = 0.7f;
+
+ /**
* Controller used to track StatusBar state to know when to show the big_clock_container.
*/
private final StatusBarStateController mStatusBarStateController;
@@ -71,10 +74,8 @@
*/
private final Transition mTransition;
- /**
- * Listener for layout transitions.
- */
- private final Transition.TransitionListener mTransitionListener;
+ private final ClockVisibilityTransition mClockTransition;
+ private final ClockVisibilityTransition mBoldClockTransition;
/**
* Optional/alternative clock injected via plugin.
@@ -156,8 +157,19 @@
mStatusBarState = mStatusBarStateController.getState();
mSysuiColorExtractor = colorExtractor;
mClockManager = clockManager;
- mTransition = new ClockBoundsTransition();
- mTransitionListener = new ClockBoundsTransitionListener();
+
+ mClockTransition = new ClockVisibilityTransition().setCutoff(
+ 1 - TO_BOLD_TRANSITION_FRACTION);
+ mClockTransition.addTarget(R.id.default_clock_view);
+ mBoldClockTransition = new ClockVisibilityTransition().setCutoff(
+ TO_BOLD_TRANSITION_FRACTION);
+ mBoldClockTransition.addTarget(R.id.default_clock_view_bold);
+ mTransition = new TransitionSet()
+ .setOrdering(TransitionSet.ORDERING_TOGETHER)
+ .addTransition(mClockTransition)
+ .addTransition(mBoldClockTransition)
+ .setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION / 2)
+ .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
}
/**
@@ -182,7 +194,6 @@
mClockManager.addOnClockChangedListener(mClockChangedListener);
mStatusBarStateController.addCallback(mStateListener);
mSysuiColorExtractor.addOnColorsChangedListener(mColorsListener);
- mTransition.addListener(mTransitionListener);
updateColors();
}
@@ -192,7 +203,6 @@
mClockManager.removeOnClockChangedListener(mClockChangedListener);
mStatusBarStateController.removeCallback(mStateListener);
mSysuiColorExtractor.removeOnColorsChangedListener(mColorsListener);
- mTransition.removeListener(mTransitionListener);
setClockPlugin(null);
}
@@ -287,7 +297,6 @@
public void setTextSize(int unit, float size) {
mClockView.setTextSize(unit, size);
- mClockViewBold.setTextSize(unit, size);
}
public void setFormat12Hour(CharSequence format) {
@@ -390,23 +399,46 @@
* Sets if the keyguard slice is showing a center-aligned header. We need a smaller clock in
* these cases.
*/
- public void setKeyguardShowingHeader(boolean hasHeader) {
+ void setKeyguardShowingHeader(boolean hasHeader) {
if (mShowingHeader == hasHeader || hasCustomClock()) {
return;
}
mShowingHeader = hasHeader;
+ float smallFontSize = mContext.getResources().getDimensionPixelSize(
+ R.dimen.widget_small_font_size);
+ float bigFontSize = mContext.getResources().getDimensionPixelSize(
+ R.dimen.widget_big_font_size);
+ mClockTransition.setScale(smallFontSize / bigFontSize);
+ mBoldClockTransition.setScale(bigFontSize / smallFontSize);
+
TransitionManager.beginDelayedTransition((ViewGroup) mClockView.getParent(), mTransition);
- int fontSize = mContext.getResources().getDimensionPixelSize(mShowingHeader
- ? R.dimen.widget_small_font_size : R.dimen.widget_big_font_size);
- int paddingBottom = mContext.getResources().getDimensionPixelSize(mShowingHeader
- ? R.dimen.widget_vertical_padding_clock : R.dimen.header_subtitle_padding);
- mClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
- mClockViewBold.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
+ mClockView.setVisibility(hasHeader ? View.INVISIBLE : View.VISIBLE);
+ mClockViewBold.setVisibility(hasHeader ? View.VISIBLE : View.INVISIBLE);
+ int paddingBottom = mContext.getResources().getDimensionPixelSize(hasHeader
+ ? R.dimen.widget_vertical_padding_clock : R.dimen.title_clock_padding);
mClockView.setPadding(mClockView.getPaddingLeft(), mClockView.getPaddingTop(),
mClockView.getPaddingRight(), paddingBottom);
mClockViewBold.setPadding(mClockViewBold.getPaddingLeft(), mClockViewBold.getPaddingTop(),
mClockViewBold.getPaddingRight(), paddingBottom);
+
+ if (hasHeader) {
+ // After the transition, make the default clock GONE so that it doesn't make the
+ // KeyguardStatusView appear taller in KeyguardClockPositionAlgorithm and elsewhere.
+ mTransition.addListener(new TransitionListenerAdapter() {
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ super.onTransitionEnd(transition);
+ // Check that header is actually showing. I saw issues where this event was
+ // fired after the big clock transitioned back to visible, which causes the time
+ // to completely disappear.
+ if (mShowingHeader) {
+ mClockView.setVisibility(View.GONE);
+ }
+ transition.removeListener(this);
+ }
+ });
+ }
}
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
@@ -434,91 +466,114 @@
}
/**
- * Special layout transition that scales the clock view as its bounds change, to make it look
- * like the text is shrinking.
+ * {@link Visibility} transformation that scales the view while it is disappearing/appearing and
+ * transitions suddenly at a cutoff fraction during the animation.
*/
- private class ClockBoundsTransition extends ChangeBounds {
+ private class ClockVisibilityTransition extends android.transition.Visibility {
+
+ private static final String PROPNAME_VISIBILITY = "systemui:keyguard:visibility";
+
+ private float mCutoff;
+ private float mScale;
/**
- * Animation fraction when text is transitioned to/from bold.
+ * Constructs a transition that switches between visible/invisible at a cutoff and scales in
+ * size while appearing/disappearing.
*/
- private static final float TO_BOLD_TRANSITION_FRACTION = 0.7f;
+ ClockVisibilityTransition() {
+ setCutoff(1f);
+ setScale(1f);
+ }
- ClockBoundsTransition() {
- setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION / 2);
- setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ /**
+ * Sets the transition point between visible/invisible.
+ *
+ * @param cutoff The fraction in [0, 1] when the view switches between visible/invisible.
+ * @return This transition object
+ */
+ public ClockVisibilityTransition setCutoff(float cutoff) {
+ mCutoff = cutoff;
+ return this;
+ }
+
+ /**
+ * Sets the scale factor applied while appearing/disappearing.
+ *
+ * @param scale Scale factor applied while appearing/disappearing. When factor is less than
+ * one, the view will shrink while disappearing. When it is greater than one,
+ * the view will expand while disappearing.
+ * @return This transition object
+ */
+ public ClockVisibilityTransition setScale(float scale) {
+ mScale = scale;
+ return this;
}
@Override
- public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ captureVisibility(transitionValues);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ captureVisibility(transitionValues);
+ }
+
+ private void captureVisibility(TransitionValues transitionValues) {
+ transitionValues.values.put(PROPNAME_VISIBILITY,
+ transitionValues.view.getVisibility());
+ }
+
+ @Override
+ public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
TransitionValues endValues) {
- Animator animator = super.createAnimator(sceneRoot, startValues, endValues);
- if (animator == null || startValues.view != mClockView) {
- return animator;
- }
+ final float cutoff = mCutoff;
+ final int startVisibility = View.INVISIBLE;
+ final int endVisibility = (int) endValues.values.get(PROPNAME_VISIBILITY);
+ final float startScale = mScale;
+ final float endScale = 1f;
+ return createAnimator(view, cutoff, startVisibility, endVisibility, startScale,
+ endScale);
+ }
- ValueAnimator boundsAnimator = null;
- if (animator instanceof AnimatorSet) {
- Animator first = ((AnimatorSet) animator).getChildAnimations().get(0);
- if (first instanceof ValueAnimator) {
- boundsAnimator = (ValueAnimator) first;
+ @Override
+ public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+ TransitionValues endValues) {
+ final float cutoff = 1f - mCutoff;
+ final int startVisibility = View.VISIBLE;
+ final int endVisibility = (int) endValues.values.get(PROPNAME_VISIBILITY);
+ final float startScale = 1f;
+ final float endScale = mScale;
+ return createAnimator(view, cutoff, startVisibility, endVisibility, startScale,
+ endScale);
+ }
+
+ private Animator createAnimator(View view, float cutoff, int startVisibility,
+ int endVisibility, float startScale, float endScale) {
+ view.setPivotY(view.getHeight() - view.getPaddingBottom());
+ view.setVisibility(startVisibility);
+ ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
+ animator.addUpdateListener(animation -> {
+ final float fraction = animation.getAnimatedFraction();
+ if (fraction > cutoff) {
+ view.setVisibility(endVisibility);
}
- } else if (animator instanceof ValueAnimator) {
- boundsAnimator = (ValueAnimator) animator;
- }
-
- if (boundsAnimator != null) {
- float bigFontSize = mContext.getResources()
- .getDimensionPixelSize(R.dimen.widget_big_font_size);
- float smallFontSize = mContext.getResources()
- .getDimensionPixelSize(R.dimen.widget_small_font_size);
- float startScale = mShowingHeader
- ? bigFontSize / smallFontSize : smallFontSize / bigFontSize;
- final int normalViewVisibility = mShowingHeader ? View.INVISIBLE : View.VISIBLE;
- final int boldViewVisibility = mShowingHeader ? View.VISIBLE : View.INVISIBLE;
- final float boldTransitionFraction = mShowingHeader ? TO_BOLD_TRANSITION_FRACTION :
- 1f - TO_BOLD_TRANSITION_FRACTION;
- boundsAnimator.addUpdateListener(animation -> {
- final float fraction = animation.getAnimatedFraction();
- if (fraction > boldTransitionFraction) {
- mClockView.setVisibility(normalViewVisibility);
- mClockViewBold.setVisibility(boldViewVisibility);
- }
- float scale = MathUtils.lerp(startScale, 1f /* stop */,
- animation.getAnimatedFraction());
- mClockView.setPivotX(mClockView.getWidth() / 2f);
- mClockViewBold.setPivotX(mClockViewBold.getWidth() / 2f);
- mClockView.setPivotY(0);
- mClockViewBold.setPivotY(0);
- mClockView.setScaleX(scale);
- mClockViewBold.setScaleX(scale);
- mClockView.setScaleY(scale);
- mClockViewBold.setScaleY(scale);
- });
- }
-
+ final float scale = MathUtils.lerp(startScale, endScale, fraction);
+ view.setScaleX(scale);
+ view.setScaleY(scale);
+ });
+ addListener(new TransitionListenerAdapter() {
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ view.setVisibility(endVisibility);
+ view.setScaleX(1f);
+ view.setScaleY(1f);
+ transition.removeListener(this);
+ }
+ });
return animator;
}
}
-
- /**
- * Transition listener for layout transition that scales the clock view.
- */
- private class ClockBoundsTransitionListener extends TransitionListenerAdapter {
-
- @Override
- public void onTransitionEnd(Transition transition) {
- mClockView.setVisibility(mShowingHeader ? View.INVISIBLE : View.VISIBLE);
- mClockViewBold.setVisibility(mShowingHeader ? View.VISIBLE : View.INVISIBLE);
- mClockView.setScaleX(1f);
- mClockViewBold.setScaleX(1f);
- mClockView.setScaleY(1f);
- mClockViewBold.setScaleY(1f);
- }
-
- @Override
- public void onTransitionCancel(Transition transition) {
- onTransitionEnd(transition);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index ae8bc52..050655c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -19,6 +19,7 @@
import android.app.Presentation;
import android.content.Context;
+import android.graphics.Color;
import android.graphics.Point;
import android.hardware.display.DisplayManager;
import android.media.MediaRouter;
@@ -32,9 +33,11 @@
import android.view.View;
import android.view.WindowManager;
+import com.android.systemui.Dependency;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.util.InjectionInflationController;
-// TODO(multi-display): Support multiple external displays
public class KeyguardDisplayManager {
protected static final String TAG = "KeyguardDisplayManager";
private static boolean DEBUG = KeyguardConstants.DEBUG;
@@ -49,6 +52,9 @@
private final SparseArray<Presentation> mPresentations = new SparseArray<>();
+ private final NavigationBarController mNavBarController =
+ Dependency.get(NavigationBarController.class);
+
private final DisplayManager.DisplayListener mDisplayListener =
new DisplayManager.DisplayListener() {
@@ -56,6 +62,7 @@
public void onDisplayAdded(int displayId) {
final Display display = mDisplayService.getDisplay(displayId);
if (mShowing) {
+ updateNavigationBarVisibility(displayId, false /* navBarVisible */);
showPresentation(display);
}
}
@@ -192,11 +199,15 @@
if (showing) {
final Display[] displays = mDisplayService.getDisplays();
for (Display display : displays) {
+ int displayId = display.getDisplayId();
+ updateNavigationBarVisibility(displayId, false /* navBarVisible */);
changed |= showPresentation(display);
}
} else {
changed = mPresentations.size() > 0;
for (int i = mPresentations.size() - 1; i >= 0; i--) {
+ int displayId = mPresentations.keyAt(i);
+ updateNavigationBarVisibility(displayId, true /* navBarVisible */);
mPresentations.valueAt(i).dismiss();
}
mPresentations.clear();
@@ -204,6 +215,25 @@
return changed;
}
+ // TODO(b/127878649): this logic is from
+ // {@link StatusBarKeyguardViewManager#updateNavigationBarVisibility}. Try to revisit a long
+ // term solution in R.
+ private void updateNavigationBarVisibility(int displayId, boolean navBarVisible) {
+ // Leave this task to {@link StatusBarKeyguardViewManager}
+ if (displayId == DEFAULT_DISPLAY) return;
+
+ NavigationBarView navBarView = mNavBarController.getNavigationBarView(displayId);
+ // We may not have nav bar on a display.
+ if (navBarView == null) return;
+
+ if (navBarVisible) {
+ navBarView.getRootView().setVisibility(View.VISIBLE);
+ } else {
+ navBarView.getRootView().setVisibility(View.GONE);
+ }
+
+ }
+
private final static class KeyguardPresentation extends Presentation {
private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height
private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s
@@ -251,6 +281,15 @@
LayoutInflater inflater = mInjectableInflater.injectable(
LayoutInflater.from(getContext()));
setContentView(inflater.inflate(R.layout.keyguard_presentation, null));
+
+ // Logic to make the lock screen fullscreen
+ getWindow().getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ getWindow().setNavigationBarContrastEnforced(false);
+ getWindow().setNavigationBarColor(Color.TRANSPARENT);
+
mClock = findViewById(R.id.clock);
// Avoid screen burn in
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 8899bd9..55499da 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -231,6 +231,13 @@
public void showUsabilityHint() {
}
+ @Override
+ public boolean disallowInterceptTouch(MotionEvent event) {
+ mTempRect.set(mLockPatternView.getLeft(), mLockPatternView.getTop(),
+ mLockPatternView.getRight(), mLockPatternView.getBottom());
+ return mTempRect.contains((int) event.getX(), (int) event.getY());
+ }
+
/** TODO: hook this up */
public void cleanUp() {
if (DEBUG) Log.v(TAG, "Cleanup() called on " + this);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 6f58159..0914fb8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -20,18 +20,25 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.res.ColorStateList;
+import android.graphics.Rect;
import android.metrics.LogMaker;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
import android.util.StatsLog;
+import android.util.TypedValue;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.widget.FrameLayout;
import androidx.annotation.VisibleForTesting;
+import androidx.dynamicanimation.animation.DynamicAnimation;
+import androidx.dynamicanimation.animation.SpringAnimation;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -60,6 +67,11 @@
// Bouncer is dismissed due to sim card unlock code entered.
private static final int BOUNCER_DISMISS_SIM = 4;
+ // Make the view move slower than the finger, as if the spring were applying force.
+ private static final float TOUCH_Y_MULTIPLIER = 0.25f;
+ // How much you need to drag the bouncer to trigger an auth retry (in dps.)
+ private static final float MIN_DRAG_SIZE = 10;
+
private KeyguardSecurityModel mSecurityModel;
private LockPatternUtils mLockPatternUtils;
@@ -70,10 +82,18 @@
private SecurityCallback mSecurityCallback;
private AlertDialog mAlertDialog;
private InjectionInflationController mInjectionInflationController;
+ private boolean mSwipeUpToRetry;
+ private final ViewConfiguration mViewConfiguration;
+ private final SpringAnimation mSpringAnimation;
+ private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
private final KeyguardUpdateMonitor mUpdateMonitor;
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
+ private float mLastTouchY = -1;
+ private int mActivePointerId = -1;
+ private boolean mIsDragging;
+ private float mStartTouchY = -1;
// Used to notify the container when something interesting happens.
public interface SecurityCallback {
@@ -104,9 +124,10 @@
mSecurityModel = new KeyguardSecurityModel(context);
mLockPatternUtils = new LockPatternUtils(context);
mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
-
+ mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
mInjectionInflationController = new InjectionInflationController(
SystemUIFactory.getInstance().getRootComponent());
+ mViewConfiguration = ViewConfiguration.get(context);
}
public void setSecurityCallback(SecurityCallback callback) {
@@ -118,6 +139,7 @@
if (mCurrentSecuritySelection != SecurityMode.None) {
getSecurityView(mCurrentSecuritySelection).onResume(reason);
}
+ updateBiometricRetry();
}
@Override
@@ -131,6 +153,95 @@
}
}
+ @Override
+ public boolean shouldDelayChildPressedState() {
+ return true;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ int pointerIndex = event.getActionIndex();
+ mStartTouchY = event.getY(pointerIndex);
+ mActivePointerId = event.getPointerId(pointerIndex);
+ mVelocityTracker.clear();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (mIsDragging) {
+ return true;
+ }
+ if (!mSwipeUpToRetry) {
+ return false;
+ }
+ // Avoid dragging the pattern view
+ if (mCurrentSecurityView.disallowInterceptTouch(event)) {
+ return false;
+ }
+ int index = event.findPointerIndex(mActivePointerId);
+ int touchSlop = mViewConfiguration.getScaledTouchSlop();
+ if (mCurrentSecurityView != null && index != -1
+ && mStartTouchY - event.getY(index) > touchSlop) {
+ mIsDragging = true;
+ return true;
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ mIsDragging = false;
+ break;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ final int action = event.getActionMasked();
+ switch (action) {
+ case MotionEvent.ACTION_MOVE:
+ mVelocityTracker.addMovement(event);
+ int pointerIndex = event.findPointerIndex(mActivePointerId);
+ float y = event.getY(pointerIndex);
+ if (mLastTouchY != -1) {
+ float dy = y - mLastTouchY;
+ setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER);
+ }
+ mLastTouchY = y;
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mActivePointerId = -1;
+ mLastTouchY = -1;
+ mIsDragging = false;
+ startSpringAnimation(mVelocityTracker.getYVelocity());
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ int index = event.getActionIndex();
+ int pointerId = event.getPointerId(index);
+ if (pointerId == mActivePointerId) {
+ // This was our active pointer going up. Choose a new
+ // active pointer and adjust accordingly.
+ final int newPointerIndex = index == 0 ? 1 : 0;
+ mLastTouchY = event.getY(newPointerIndex);
+ mActivePointerId = event.getPointerId(newPointerIndex);
+ }
+ break;
+ }
+ if (action == MotionEvent.ACTION_UP) {
+ if (-getTranslationY() > TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ MIN_DRAG_SIZE, getResources().getDisplayMetrics())) {
+ mUpdateMonitor.requestFaceAuth();
+ }
+ }
+ return true;
+ }
+
+ private void startSpringAnimation(float startVelocity) {
+ mSpringAnimation
+ .setStartVelocity(startVelocity)
+ .animateToFinalPosition(0);
+ }
+
public void startAppearAnimation() {
if (mCurrentSecuritySelection != SecurityMode.None) {
getSecurityView(mCurrentSecuritySelection).startAppearAnimation();
@@ -145,6 +256,18 @@
return false;
}
+ /**
+ * Enables/disables swipe up to retry on the bouncer.
+ */
+ private void updateBiometricRetry() {
+ SecurityMode securityMode = getSecurityMode();
+ int userId = KeyguardUpdateMonitor.getCurrentUser();
+ mSwipeUpToRetry = mUpdateMonitor.isUnlockWithFacePossible(userId)
+ && securityMode != SecurityMode.SimPin
+ && securityMode != SecurityMode.SimPuk
+ && securityMode != SecurityMode.None;
+ }
+
public CharSequence getTitle() {
return mSecurityViewFlipper.getTitle();
}
@@ -195,6 +318,14 @@
mSecurityViewFlipper.setLockPatternUtils(mLockPatternUtils);
}
+ @Override
+ protected boolean fitSystemWindows(Rect insets) {
+ // Consume bottom insets because we're setting the padding locally (for IME and navbar.)
+ setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), insets.bottom);
+ insets.bottom = 0;
+ return false;
+ }
+
private void showDialog(String title, String message) {
if (mAlertDialog != null) {
mAlertDialog.dismiss();
@@ -467,7 +598,6 @@
}
public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
- KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
if (success) {
StatsLog.write(StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED,
StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__RESULT__SUCCESS);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
index 272b3bd..e108194 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
@@ -16,6 +16,7 @@
package com.android.keyguard;
import android.content.res.ColorStateList;
+import android.view.MotionEvent;
import com.android.internal.widget.LockPatternUtils;
@@ -137,4 +138,14 @@
* @return The View's title.
*/
CharSequence getTitle();
+
+ /**
+ * If the parent should not be allowed to intercept touch events.
+ * @param event A touch event.
+ * @return {@code true} if touch should be passed forward.
+ * @see android.view.ViewGroup#requestDisallowInterceptTouchEvent(boolean)
+ */
+ default boolean disallowInterceptTouch(MotionEvent event) {
+ return false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index c1bf4d4..e219e24 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -38,6 +38,7 @@
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.TypedValue;
import android.view.View;
import android.view.animation.Animation;
import android.widget.Button;
@@ -98,6 +99,7 @@
private LiveData<Slice> mLiveData;
private int mDisplayId = INVALID_DISPLAY;
private int mIconSize;
+ private int mIconSizeWithHeader;
/**
* Runnable called whenever the view contents change.
*/
@@ -106,6 +108,8 @@
private boolean mHasHeader;
private final int mRowWithHeaderPadding;
private final int mRowPadding;
+ private float mRowTextSize;
+ private float mRowWithHeaderTextSize;
@Inject
public KeyguardSliceView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
@@ -141,6 +145,11 @@
mRow = findViewById(R.id.row);
mTextColor = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor);
mIconSize = (int) mContext.getResources().getDimension(R.dimen.widget_icon_size);
+ mIconSizeWithHeader = (int) mContext.getResources().getDimension(R.dimen.header_icon_size);
+ mRowTextSize = mContext.getResources().getDimensionPixelSize(
+ R.dimen.widget_label_font_size);
+ mRowWithHeaderTextSize = mContext.getResources().getDimensionPixelSize(
+ R.dimen.header_row_font_size);
mTitle.setOnClickListener(this);
}
@@ -244,16 +253,19 @@
final SliceItem titleItem = rc.getTitleItem();
button.setText(titleItem == null ? null : titleItem.getText());
button.setContentDescription(rc.getContentDescription());
+ button.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+ mHasHeader ? mRowWithHeaderTextSize : mRowTextSize);
Drawable iconDrawable = null;
SliceItem icon = SliceQuery.find(item.getSlice(),
android.app.slice.SliceItem.FORMAT_IMAGE);
if (icon != null) {
+ final int iconSize = mHasHeader ? mIconSizeWithHeader : mIconSize;
iconDrawable = icon.getIcon().loadDrawable(mContext);
if (iconDrawable != null) {
final int width = (int) (iconDrawable.getIntrinsicWidth()
- / (float) iconDrawable.getIntrinsicHeight() * mIconSize);
- iconDrawable.setBounds(0, 0, Math.max(width, 1), mIconSize);
+ / (float) iconDrawable.getIntrinsicHeight() * iconSize);
+ iconDrawable.setBounds(0, 0, Math.max(width, 1), iconSize);
}
}
button.setCompoundDrawables(iconDrawable, null, null, null);
@@ -361,6 +373,11 @@
@Override
public void onDensityOrFontScaleChanged() {
mIconSize = mContext.getResources().getDimensionPixelSize(R.dimen.widget_icon_size);
+ mIconSizeWithHeader = (int) mContext.getResources().getDimension(R.dimen.header_icon_size);
+ mRowTextSize = mContext.getResources().getDimensionPixelSize(
+ R.dimen.widget_label_font_size);
+ mRowWithHeaderTextSize = mContext.getResources().getDimensionPixelSize(
+ R.dimen.header_row_font_size);
}
public void refresh() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index b02d514..1dc3474 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -33,6 +33,7 @@
import android.util.TypedValue;
import android.view.View;
import android.widget.GridLayout;
+import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.core.graphics.ColorUtils;
@@ -55,6 +56,7 @@
private final LockPatternUtils mLockPatternUtils;
private final IActivityManager mIActivityManager;
+ private LinearLayout mStatusViewContainer;
private TextView mLogoutView;
private KeyguardClockSwitch mClockView;
private TextView mOwnerInfo;
@@ -66,6 +68,14 @@
private float mDarkAmount = 0;
private int mTextColor;
+ /**
+ * Bottom margin that defines the margin between bottom of smart space and top of notification
+ * icons on AOD.
+ */
+ private int mBottomMargin;
+ private int mBottomMarginWithHeader;
+ private boolean mShowingHeader;
+
private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
@Override
@@ -161,6 +171,7 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ mStatusViewContainer = findViewById(R.id.status_view_container);
mLogoutView = findViewById(R.id.logout);
if (mLogoutView != null) {
mLogoutView.setOnClickListener(this::onLogoutClicked);
@@ -190,7 +201,19 @@
* Moves clock, adjusting margins when slice content changes.
*/
private void onSliceContentChanged() {
- mClockView.setKeyguardShowingHeader(mKeyguardSlice.hasHeader());
+ final boolean hasHeader = mKeyguardSlice.hasHeader();
+ mClockView.setKeyguardShowingHeader(hasHeader);
+ if (mShowingHeader == hasHeader) {
+ return;
+ }
+ mShowingHeader = hasHeader;
+ // Update bottom margin since header has appeared/disappeared.
+ if (mStatusViewContainer != null) {
+ MarginLayoutParams params = (MarginLayoutParams) mStatusViewContainer.getLayoutParams();
+ params.setMargins(params.leftMargin, params.topMargin, params.rightMargin,
+ hasHeader ? mBottomMarginWithHeader : mBottomMargin);
+ mStatusViewContainer.setLayoutParams(params);
+ }
}
@Override
@@ -209,6 +232,7 @@
mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimensionPixelSize(R.dimen.widget_label_font_size));
}
+ loadBottomMargin();
}
public void dozeTimeTick() {
@@ -318,6 +342,12 @@
}
}
+ private void loadBottomMargin() {
+ mBottomMargin = getResources().getDimensionPixelSize(R.dimen.widget_vertical_padding);
+ mBottomMarginWithHeader = getResources().getDimensionPixelSize(
+ R.dimen.widget_vertical_padding_with_header);
+ }
+
// DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often.
// This is an optimization to ensure we only recompute the patterns when the inputs change.
private static final class Patterns {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 83b98b0..dd6ccb2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1686,7 +1686,11 @@
&& mFpm.getEnrolledFingerprints(userId).size() > 0;
}
- private boolean isUnlockWithFacePossible(int userId) {
+ /**
+ * If face hardware is available and user has enrolled. Not considering encryption or
+ * lockdown state.
+ */
+ public boolean isUnlockWithFacePossible(int userId) {
return mFaceManager != null && mFaceManager.isHardwareDetected()
&& !isFaceDisabled(userId)
&& mFaceManager.hasEnrolledTemplates(userId);
@@ -2273,6 +2277,10 @@
return isSimPinSecure();
}
+ /**
+ * If any SIM cards are currently secure.
+ * @see #isSimPinSecure(State)
+ */
public boolean isSimPinSecure() {
// True if any SIM is pin secure
for (SubscriptionInfo info : getSubscriptionInfo(false /* forceReload */)) {
@@ -2338,11 +2346,13 @@
return changed;
}
+ /**
+ * If the {@code state} is currently requiring a SIM PIN, PUK, or is disabled.
+ */
public static boolean isSimPinSecure(IccCardConstants.State state) {
- final IccCardConstants.State simState = state;
- return (simState == IccCardConstants.State.PIN_REQUIRED
- || simState == IccCardConstants.State.PUK_REQUIRED
- || simState == IccCardConstants.State.PERM_DISABLED);
+ return (state == IccCardConstants.State.PIN_REQUIRED
+ || state == IccCardConstants.State.PUK_REQUIRED
+ || state == IccCardConstants.State.PERM_DISABLED);
}
public DisplayClientState getCachedDisplayClientState() {
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
index eec1d70..f468eca 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
@@ -21,7 +21,6 @@
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint.Style;
-import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextClock;
@@ -96,11 +95,8 @@
mView = mLayoutInflater.inflate(R.layout.digital_clock, null);
mLockClock = mView.findViewById(R.id.lock_screen_clock);
- final int textSize = mResources.getDimensionPixelSize(R.dimen.widget_title_font_size);
- mLockClock.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
-
@Override
public void onDestroyView() {
mBigClockView = null;
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
index 5fec61b..61a6952 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
@@ -21,7 +21,6 @@
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint.Style;
-import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextClock;
@@ -96,8 +95,6 @@
mLockClockContainer = mLayoutInflater.inflate(R.layout.digital_clock, null);
mLockClock = (TextClock) mLockClockContainer.findViewById(R.id.lock_screen_clock);
- final int textSize = mResources.getDimensionPixelSize(R.dimen.widget_title_font_size);
- mLockClock.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 07c2f10..9f4c403e 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -32,7 +32,6 @@
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Observer;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManager.DockEventListener;
@@ -89,6 +88,7 @@
private final Observer<Integer> mCurrentUserObserver = (newUserId) -> reload();
private final PluginManager mPluginManager;
+ @Nullable private final DockManager mDockManager;
/**
* Observe changes to dock state to know when to switch the clock face.
@@ -102,7 +102,6 @@
reload();
}
};
- @Nullable private DockManager mDockManager;
/**
* When docked, the DOCKED_CLOCK_FACE setting will be checked for the custom clock face
@@ -125,21 +124,24 @@
@Inject
public ClockManager(Context context, InjectionInflationController injectionInflater,
- PluginManager pluginManager, SysuiColorExtractor colorExtractor) {
+ PluginManager pluginManager, SysuiColorExtractor colorExtractor,
+ @Nullable DockManager dockManager) {
this(context, injectionInflater, pluginManager, colorExtractor,
context.getContentResolver(), new CurrentUserObservable(context),
- new SettingsWrapper(context.getContentResolver()));
+ new SettingsWrapper(context.getContentResolver()), dockManager);
}
+ @VisibleForTesting
ClockManager(Context context, InjectionInflationController injectionInflater,
PluginManager pluginManager, SysuiColorExtractor colorExtractor,
ContentResolver contentResolver, CurrentUserObservable currentUserObservable,
- SettingsWrapper settingsWrapper) {
+ SettingsWrapper settingsWrapper, DockManager dockManager) {
mContext = context;
mPluginManager = pluginManager;
mContentResolver = contentResolver;
mSettingsWrapper = settingsWrapper;
mCurrentUserObservable = currentUserObservable;
+ mDockManager = dockManager;
mPreviewClocks = new AvailableClocks();
Resources res = context.getResources();
@@ -223,9 +225,6 @@
Settings.Secure.getUriFor(Settings.Secure.DOCKED_CLOCK_FACE),
false, mContentObserver, UserHandle.USER_ALL);
mCurrentUserObservable.getCurrentUser().observeForever(mCurrentUserObserver);
- if (mDockManager == null) {
- mDockManager = SysUiServiceProvider.getComponent(mContext, DockManager.class);
- }
if (mDockManager != null) {
mDockManager.addListener(mDockEventListener);
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 4b6306a..7a82402 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -15,6 +15,7 @@
package com.android.systemui;
import android.annotation.Nullable;
+import android.app.INotificationManager;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.SensorPrivacyManager;
@@ -41,6 +42,7 @@
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -68,6 +70,7 @@
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -298,6 +301,9 @@
@Inject Lazy<SensorPrivacyController> mSensorPrivacyController;
@Inject Lazy<DumpController> mDumpController;
@Inject Lazy<DockManager> mDockManager;
+ @Inject Lazy<ChannelEditorDialogController> mChannelEditorDialogController;
+ @Inject Lazy<INotificationManager> mINotificationManager;
+ @Inject Lazy<FalsingManager> mFalsingManager;
@Inject
public Dependency() {
@@ -473,6 +479,9 @@
mProviders.put(SensorPrivacyController.class, mSensorPrivacyController::get);
mProviders.put(DumpController.class, mDumpController::get);
mProviders.put(DockManager.class, mDockManager::get);
+ mProviders.put(ChannelEditorDialogController.class, mChannelEditorDialogController::get);
+ mProviders.put(INotificationManager.class, mINotificationManager::get);
+ mProviders.put(FalsingManager.class, mFalsingManager::get);
// TODO(b/118592525): to support multi-display , we start to add something which is
// per-display, while others may be global. I think it's time to add
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
index 53050bf..057d70c 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
@@ -18,8 +18,10 @@
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.appops.AppOpsControllerImpl;
+import com.android.systemui.classifier.FalsingManagerProxy;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.PowerNotificationWarnings;
@@ -234,4 +236,9 @@
*/
@Binds
public abstract QSHost provideQsHost(QSTileHost controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract FalsingManager provideFalsingmanager(FalsingManagerProxy falsingManagerImpl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
index f649976..321206f 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
@@ -22,6 +22,7 @@
import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
import android.annotation.Nullable;
+import android.app.INotificationManager;
import android.content.Context;
import android.hardware.SensorPrivacyManager;
import android.hardware.display.NightDisplayListener;
@@ -132,6 +133,14 @@
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
}
+ /** */
+ @Singleton
+ @Provides
+ public INotificationManager provideINotificationManager() {
+ return INotificationManager.Stub.asInterface(
+ ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+ }
+
@Singleton
@Provides
// Single instance of DisplayMetrics, gets updated by StatusBar, but can be used
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index f7ecfd7..84e0238 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -34,7 +34,8 @@
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -112,7 +113,7 @@
mDensityScale = res.getDisplayMetrics().density;
mFalsingThreshold = res.getDimensionPixelSize(R.dimen.swipe_helper_falsing_threshold);
mFadeDependingOnAmountSwiped = res.getBoolean(R.bool.config_fadeDependingOnAmountSwiped);
- mFalsingManager = FalsingManager.getInstance(context);
+ mFalsingManager = FalsingManagerFactory.getInstance(context);
mFlingAnimationUtils = new FlingAnimationUtils(context, getMaxEscapeAnimDuration() / 1000f);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 12f40f3..61a0f72 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -205,7 +205,7 @@
final Handler mainHandler = new Handler(Looper.getMainLooper());
Dependency.get(PluginManager.class).addPluginListener(
new PluginListener<OverlayPlugin>() {
- private ArraySet<OverlayPlugin> mOverlays;
+ private ArraySet<OverlayPlugin> mOverlays = new ArraySet<>();
@Override
public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
@@ -215,18 +215,7 @@
StatusBar statusBar = getComponent(StatusBar.class);
if (statusBar != null) {
plugin.setup(statusBar.getStatusBarWindow(),
- statusBar.getNavigationBarView());
- }
- // Lazy init.
- if (mOverlays == null) mOverlays = new ArraySet<>();
- if (plugin.holdStatusBarOpen()) {
- mOverlays.add(plugin);
- Dependency.get(StatusBarWindowController.class)
- .setStateListener(b -> mOverlays.forEach(
- o -> o.setCollapseDesired(b)));
- Dependency.get(StatusBarWindowController.class)
- .setForcePluginOpen(mOverlays.size() != 0);
-
+ statusBar.getNavigationBarView(), new Callback(plugin));
}
}
});
@@ -243,6 +232,33 @@
}
});
}
+
+ class Callback implements OverlayPlugin.Callback {
+ private final OverlayPlugin mPlugin;
+
+ Callback(OverlayPlugin plugin) {
+ mPlugin = plugin;
+ }
+
+ @Override
+ public void onHoldStatusBarOpenChange() {
+ if (mPlugin.holdStatusBarOpen()) {
+ mOverlays.add(mPlugin);
+ } else {
+ mOverlays.remove(mPlugin);
+ }
+ mainHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ Dependency.get(StatusBarWindowController.class)
+ .setStateListener(b -> mOverlays.forEach(
+ o -> o.setCollapseDesired(b)));
+ Dependency.get(StatusBarWindowController.class)
+ .setForcePluginOpen(mOverlays.size() != 0);
+ }
+ });
+ }
+ }
}, OverlayPlugin.class, true /* Allow multiple plugins */);
mServicesStarted = true;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index f9926f3..0fdab01 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -33,7 +33,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.assist.AssistManager;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.dock.DockManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -129,8 +129,9 @@
DismissCallbackRegistry dismissCallbackRegistry,
KeyguardBouncer.BouncerExpansionCallback expansionCallback) {
return new KeyguardBouncer(context, callback, lockPatternUtils, container,
- dismissCallbackRegistry, FalsingManager.getInstance(context), expansionCallback,
- KeyguardUpdateMonitor.getInstance(context), new Handler(Looper.getMainLooper()));
+ dismissCallbackRegistry, FalsingManagerFactory.getInstance(context),
+ expansionCallback, KeyguardUpdateMonitor.getInstance(context),
+ new Handler(Looper.getMainLooper()));
}
public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 4ed28f9..68cf15d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -15,6 +15,7 @@
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.metrics.LogMaker;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Bundle;
@@ -35,6 +36,8 @@
import com.android.internal.app.AssistUtils;
import com.android.internal.app.IVoiceInteractionSessionListener;
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.ConfigurationChangedReceiver;
@@ -185,6 +188,10 @@
args = new Bundle();
}
args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.uptimeMillis());
+ // Logs assistant start with invocation type.
+ MetricsLogger.action(
+ new LogMaker(MetricsEvent.ASSISTANT)
+ .setType(MetricsEvent.TYPE_OPEN).setSubtype(args.getInt(INVOCATION_TYPE_KEY)));
startAssistInternal(args, assistComponent, isService);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index 420d0fa..45c19ad 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -76,8 +76,7 @@
}
case MSG_BIOMETRIC_HELP: {
SomeArgs args = (SomeArgs) msg.obj;
- handleBiometricHelp((String) args.arg1 /* message */,
- (boolean) args.arg2 /* requireTryAgain */);
+ handleBiometricHelp((String) args.arg1 /* message */);
args.recycle();
break;
}
@@ -182,7 +181,6 @@
if (DEBUG) Log.d(TAG, "onBiometricHelp: " + message);
SomeArgs args = SomeArgs.obtain();
args.arg1 = message;
- args.arg2 = false; // requireTryAgain
mHandler.obtainMessage(MSG_BIOMETRIC_HELP, args).sendToTarget();
}
@@ -257,14 +255,13 @@
}, mCurrentDialog.getDelayAfterAuthenticatedDurationMs());
}
} else {
- handleBiometricHelp(failureReason, true /* requireTryAgain */);
- mCurrentDialog.showTryAgainButton(true /* show */);
+ mCurrentDialog.onAuthenticationFailed(failureReason);
}
}
- private void handleBiometricHelp(String message, boolean requireTryAgain) {
+ private void handleBiometricHelp(String message) {
if (DEBUG) Log.d(TAG, "handleBiometricHelp: " + message);
- mCurrentDialog.showHelpMessage(message, requireTryAgain);
+ mCurrentDialog.onHelpReceived(message);
}
private void handleBiometricError(String error) {
@@ -273,7 +270,7 @@
if (DEBUG) Log.d(TAG, "Dialog already dismissed");
return;
}
- mCurrentDialog.showErrorMessage(error);
+ mCurrentDialog.onErrorReceived(error);
}
private void handleHideDialog(boolean userCanceled) {
@@ -328,7 +325,6 @@
private void handleTryAgainPressed() {
try {
- mCurrentDialog.clearTemporaryMessage();
mReceiver.onTryAgainPressed();
} catch (RemoteException e) {
Log.e(TAG, "RemoteException when handling try again", e);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
index 32a7678..5717a54 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
@@ -18,10 +18,8 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
-import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
-import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricPrompt;
import android.os.Binder;
@@ -35,7 +33,6 @@
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -58,11 +55,16 @@
private static final String KEY_TRY_AGAIN_VISIBILITY = "key_try_again_visibility";
private static final String KEY_CONFIRM_VISIBILITY = "key_confirm_visibility";
+ private static final String KEY_STATE = "key_state";
+ private static final String KEY_ERROR_TEXT_VISIBILITY = "key_error_text_visibility";
+ private static final String KEY_ERROR_TEXT_STRING = "key_error_text_string";
+ private static final String KEY_ERROR_TEXT_IS_TEMPORARY = "key_error_text_is_temporary";
+ private static final String KEY_ERROR_TEXT_COLOR = "key_error_text_color";
private static final int ANIMATION_DURATION_SHOW = 250; // ms
private static final int ANIMATION_DURATION_AWAY = 350; // ms
- private static final int MSG_CLEAR_MESSAGE = 1;
+ protected static final int MSG_RESET_MESSAGE = 1;
protected static final int STATE_IDLE = 0;
protected static final int STATE_AUTHENTICATING = 1;
@@ -78,7 +80,7 @@
private final float mAnimationTranslationOffset;
private final int mErrorColor;
private final float mDialogWidth;
- private final DialogViewCallback mCallback;
+ protected final DialogViewCallback mCallback;
protected final ViewGroup mLayout;
protected final LinearLayout mDialog;
@@ -94,8 +96,9 @@
protected final int mTextColor;
private Bundle mBundle;
+ private Bundle mRestoredState;
- private int mState;
+ private int mState = STATE_IDLE;
private boolean mAnimatingAway;
private boolean mWasForceRemoved;
private boolean mSkipIntro;
@@ -105,11 +108,10 @@
protected abstract int getHintStringResourceId();
protected abstract int getAuthenticatedAccessibilityResourceId();
protected abstract int getIconDescriptionResourceId();
- protected abstract Drawable getAnimationForTransition(int oldState, int newState);
- protected abstract boolean shouldAnimateForTransition(int oldState, int newState);
protected abstract int getDelayAfterAuthenticatedDurationMs();
protected abstract boolean shouldGrayAreaDismissDialog();
- protected abstract void handleClearMessage(boolean requireTryAgain);
+ protected abstract void handleResetMessage();
+ protected abstract void updateIcon(int oldState, int newState);
private final Runnable mShowAnimationRunnable = new Runnable() {
@Override
@@ -125,16 +127,17 @@
.setDuration(ANIMATION_DURATION_SHOW)
.setInterpolator(mLinearOutSlowIn)
.withLayer()
+ .withEndAction(() -> onDialogAnimatedIn())
.start();
}
};
- private Handler mHandler = new Handler() {
+ protected Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
- case MSG_CLEAR_MESSAGE:
- handleClearMessage((boolean) msg.obj /* requireTryAgain */);
+ case MSG_RESET_MESSAGE:
+ handleResetMessage();
break;
default:
Log.e(TAG, "Unhandled message: " + msg.what);
@@ -152,12 +155,8 @@
mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
mAnimationTranslationOffset = getResources()
.getDimension(R.dimen.biometric_dialog_animation_translation_offset);
-
- TypedArray array = getContext().obtainStyledAttributes(
- new int[]{android.R.attr.colorError, android.R.attr.textColorSecondary});
- mErrorColor = array.getColor(0, 0);
- mTextColor = array.getColor(1, 0);
- array.recycle();
+ mErrorColor = getResources().getColor(R.color.biometric_dialog_error);
+ mTextColor = getResources().getColor(R.color.biometric_dialog_gray);
DisplayMetrics metrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(metrics);
@@ -224,26 +223,27 @@
});
mTryAgainButton.setOnClickListener((View v) -> {
+ handleResetMessage();
+ updateState(STATE_AUTHENTICATING);
showTryAgainButton(false /* show */);
- handleClearMessage(false /* requireTryAgain */);
mCallback.onTryAgainPressed();
});
-
- mLayout.setFocusableInTouchMode(true);
- mLayout.requestFocus();
}
public void onSaveState(Bundle bundle) {
bundle.putInt(KEY_TRY_AGAIN_VISIBILITY, mTryAgainButton.getVisibility());
bundle.putInt(KEY_CONFIRM_VISIBILITY, mPositiveButton.getVisibility());
+ bundle.putInt(KEY_STATE, mState);
+ bundle.putInt(KEY_ERROR_TEXT_VISIBILITY, mErrorText.getVisibility());
+ bundle.putCharSequence(KEY_ERROR_TEXT_STRING, mErrorText.getText());
+ bundle.putBoolean(KEY_ERROR_TEXT_IS_TEMPORARY, mHandler.hasMessages(MSG_RESET_MESSAGE));
+ bundle.putInt(KEY_ERROR_TEXT_COLOR, mErrorText.getCurrentTextColor());
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
- mErrorText.setText(getHintStringResourceId());
-
final ImageView backgroundView = mLayout.findViewById(R.id.background);
if (mUserManager.isManagedProfile(mUserId)) {
@@ -258,20 +258,24 @@
}
mNegativeButton.setVisibility(View.VISIBLE);
- mErrorText.setVisibility(View.VISIBLE);
if (RotationUtils.getRotation(mContext) != RotationUtils.ROTATION_NONE) {
mDialog.getLayoutParams().width = (int) mDialogWidth;
}
- mState = STATE_IDLE;
- updateState(STATE_AUTHENTICATING);
+ if (mRestoredState == null) {
+ updateState(STATE_AUTHENTICATING);
+ mErrorText.setText(getHintStringResourceId());
+ mErrorText.setContentDescription(mContext.getString(getHintStringResourceId()));
+ mErrorText.setVisibility(View.VISIBLE);
+ } else {
+ updateState(mState);
+ }
CharSequence titleText = mBundle.getCharSequence(BiometricPrompt.KEY_TITLE);
mTitleText.setVisibility(View.VISIBLE);
mTitleText.setText(titleText);
- mTitleText.setSelected(true);
final CharSequence subtitleText = mBundle.getCharSequence(BiometricPrompt.KEY_SUBTITLE);
if (TextUtils.isEmpty(subtitleText)) {
@@ -292,7 +296,7 @@
mNegativeButton.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT));
- if (requiresConfirmation()) {
+ if (requiresConfirmation() && mRestoredState == null) {
mPositiveButton.setVisibility(View.VISIBLE);
mPositiveButton.setEnabled(false);
}
@@ -314,32 +318,12 @@
mSkipIntro = false;
}
- protected void updateIcon(int lastState, int newState) {
- final Drawable icon = getAnimationForTransition(lastState, newState);
- if (icon == null) {
- Log.e(TAG, "Animation not found, " + lastState + " -> " + newState);
- return;
- }
-
- final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
- ? (AnimatedVectorDrawable) icon
- : null;
-
- mBiometricIcon.setImageDrawable(icon);
-
- if (animation != null && shouldAnimateForTransition(lastState, newState)) {
- animation.forceAnimationOnUI();
- animation.start();
- }
- }
-
private void setDismissesDialog(View v) {
v.setClickable(true);
- v.setOnTouchListener((View view, MotionEvent event) -> {
+ v.setOnClickListener(v1 -> {
if (mState != STATE_AUTHENTICATED && shouldGrayAreaDismissDialog()) {
mCallback.onUserCanceled();
}
- return true;
});
}
@@ -353,7 +337,7 @@
mWindowManager.removeView(BiometricDialogView.this);
mAnimatingAway = false;
// Set the icons / text back to normal state
- handleClearMessage(false /* requireTryAgain */);
+ handleResetMessage();
showTryAgainButton(false /* show */);
updateState(STATE_IDLE);
}
@@ -424,35 +408,46 @@
}
// Shows an error/help message
- private void showTemporaryMessage(String message, boolean requireTryAgain) {
- mHandler.removeMessages(MSG_CLEAR_MESSAGE);
- updateState(STATE_ERROR);
+ protected void showTemporaryMessage(String message) {
+ mHandler.removeMessages(MSG_RESET_MESSAGE);
mErrorText.setText(message);
mErrorText.setTextColor(mErrorColor);
mErrorText.setContentDescription(message);
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_MESSAGE, requireTryAgain),
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESET_MESSAGE),
BiometricPrompt.HIDE_DIALOG_DELAY);
}
- public void clearTemporaryMessage() {
- mHandler.removeMessages(MSG_CLEAR_MESSAGE);
- mHandler.obtainMessage(MSG_CLEAR_MESSAGE, false /* requireTryAgain */).sendToTarget();
+ /**
+ * Transient help message (acquire) is received, dialog stays showing. Sensor stays in
+ * "authenticating" state.
+ * @param message
+ */
+ public void onHelpReceived(String message) {
+ updateState(STATE_ERROR);
+ showTemporaryMessage(message);
}
- public void showHelpMessage(String message, boolean requireTryAgain) {
- showTemporaryMessage(message, requireTryAgain);
+ public void onAuthenticationFailed(String message) {
+ updateState(STATE_ERROR);
+ showTemporaryMessage(message);
}
- public void showErrorMessage(String error) {
- showTemporaryMessage(error, false /* requireTryAgain */);
+ /**
+ * Hard error is received, dialog will be dismissed soon.
+ * @param error
+ */
+ public void onErrorReceived(String error) {
+ updateState(STATE_ERROR);
+ showTemporaryMessage(error);
showTryAgainButton(false /* show */);
- mCallback.onErrorShown();
+ mCallback.onErrorShown(); // TODO: Split between fp and face
}
public void updateState(int newState) {
if (newState == STATE_PENDING_CONFIRMATION) {
- mHandler.removeMessages(MSG_CLEAR_MESSAGE);
+ mHandler.removeMessages(MSG_RESET_MESSAGE);
mErrorText.setVisibility(View.INVISIBLE);
+ mPositiveButton.setVisibility(View.VISIBLE);
mPositiveButton.setEnabled(true);
} else if (newState == STATE_AUTHENTICATED) {
mPositiveButton.setVisibility(View.GONE);
@@ -471,9 +466,27 @@
public void showTryAgainButton(boolean show) {
}
+ public void onDialogAnimatedIn() {
+ }
+
public void restoreState(Bundle bundle) {
+ mRestoredState = bundle;
mTryAgainButton.setVisibility(bundle.getInt(KEY_TRY_AGAIN_VISIBILITY));
mPositiveButton.setVisibility(bundle.getInt(KEY_CONFIRM_VISIBILITY));
+ mState = bundle.getInt(KEY_STATE);
+ mErrorText.setText(bundle.getCharSequence(KEY_ERROR_TEXT_STRING));
+ mErrorText.setContentDescription(bundle.getCharSequence(KEY_ERROR_TEXT_STRING));
+ mErrorText.setVisibility(bundle.getInt(KEY_ERROR_TEXT_VISIBILITY));
+ mErrorText.setTextColor(bundle.getInt(KEY_ERROR_TEXT_COLOR));
+
+ if (bundle.getBoolean(KEY_ERROR_TEXT_IS_TEMPORARY)) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESET_MESSAGE),
+ BiometricPrompt.HIDE_DIALOG_DELAY);
+ }
+ }
+
+ protected int getState() {
+ return mState;
}
public WindowManager.LayoutParams getLayoutParams() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java
index 28156da..8f26f18 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java
@@ -22,10 +22,14 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Outline;
+import android.graphics.drawable.Animatable2;
+import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.biometrics.BiometricPrompt;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.View;
import android.view.ViewOutlineProvider;
@@ -40,6 +44,7 @@
private static final String TAG = "FaceDialogView";
private static final String KEY_DIALOG_SIZE = "key_dialog_size";
+ private static final String KEY_DIALOG_ANIMATED_IN = "key_dialog_animated_in";
private static final int HIDE_DIALOG_DELAY = 500; // ms
private static final int IMPLICIT_Y_PADDING = 16; // dp
@@ -54,6 +59,68 @@
private int mSize;
private float mIconOriginalY;
private DialogOutlineProvider mOutlineProvider = new DialogOutlineProvider();
+ private IconController mIconController;
+ private boolean mDialogAnimatedIn;
+
+ /**
+ * Class that handles the biometric icon animations.
+ */
+ private final class IconController extends Animatable2.AnimationCallback {
+
+ private boolean mLastPulseDirection; // false = dark to light, true = light to dark
+
+ int mState;
+
+ IconController() {
+ mState = STATE_IDLE;
+ }
+
+ public void animateOnce(int iconRes) {
+ animateIcon(iconRes, false);
+ }
+
+ public void showStatic(int iconRes) {
+ mBiometricIcon.setImageDrawable(mContext.getDrawable(iconRes));
+ }
+
+ public void startPulsing() {
+ mLastPulseDirection = false;
+ animateIcon(R.drawable.face_dialog_pulse_dark_to_light, true);
+ }
+
+ public void showIcon(int iconRes) {
+ final Drawable drawable = mContext.getDrawable(iconRes);
+ mBiometricIcon.setImageDrawable(drawable);
+ }
+
+ private void animateIcon(int iconRes, boolean repeat) {
+ final AnimatedVectorDrawable icon =
+ (AnimatedVectorDrawable) mContext.getDrawable(iconRes);
+ mBiometricIcon.setImageDrawable(icon);
+ icon.forceAnimationOnUI();
+ if (repeat) {
+ icon.registerAnimationCallback(this);
+ }
+ icon.start();
+ }
+
+ private void pulseInNextDirection() {
+ int iconRes = mLastPulseDirection ? R.drawable.face_dialog_pulse_dark_to_light
+ : R.drawable.face_dialog_pulse_light_to_dark;
+ animateIcon(iconRes, true /* repeat */);
+ mLastPulseDirection = !mLastPulseDirection;
+ }
+
+ @Override
+ public void onAnimationEnd(Drawable drawable) {
+ super.onAnimationEnd(drawable);
+
+ if (mState == STATE_AUTHENTICATING) {
+ // Still authenticating, pulse the icon
+ pulseInNextDirection();
+ }
+ }
+ }
private final class DialogOutlineProvider extends ViewOutlineProvider {
@@ -79,9 +146,15 @@
}
}
+ private final Runnable mErrorToIdleAnimationRunnable = () -> {
+ updateState(STATE_IDLE);
+ mErrorText.setVisibility(View.INVISIBLE);
+ };
+
public FaceDialogView(Context context,
DialogViewCallback callback) {
super(context, callback);
+ mIconController = new IconController();
}
private void updateSize(int newSize) {
@@ -208,20 +281,18 @@
public void onSaveState(Bundle bundle) {
super.onSaveState(bundle);
bundle.putInt(KEY_DIALOG_SIZE, mSize);
+ bundle.putBoolean(KEY_DIALOG_ANIMATED_IN, mDialogAnimatedIn);
}
@Override
- protected void handleClearMessage(boolean requireTryAgain) {
- // Clears the temporary message and shows the help message. If requireTryAgain is true,
- // we will start the authenticating state again.
- if (!requireTryAgain) {
- updateState(STATE_AUTHENTICATING);
- mErrorText.setText(getHintStringResourceId());
- mErrorText.setTextColor(mTextColor);
+ protected void handleResetMessage() {
+ mErrorText.setText(getHintStringResourceId());
+ mErrorText.setContentDescription(mContext.getString(getHintStringResourceId()));
+ mErrorText.setTextColor(mTextColor);
+ if (getState() == STATE_AUTHENTICATING) {
mErrorText.setVisibility(View.VISIBLE);
} else {
- updateState(STATE_IDLE);
mErrorText.setVisibility(View.INVISIBLE);
}
}
@@ -231,6 +302,7 @@
super.restoreState(bundle);
// Keep in mind that this happens before onAttachedToWindow()
mSize = bundle.getInt(KEY_DIALOG_SIZE);
+ mDialogAnimatedIn = bundle.getBoolean(KEY_DIALOG_ANIMATED_IN);
}
/**
@@ -270,9 +342,8 @@
}
@Override
- public void showErrorMessage(String error) {
- super.showErrorMessage(error);
-
+ public void onErrorReceived(String error) {
+ super.onErrorReceived(error);
// All error messages will cause the dialog to go from small -> big. Error messages
// are messages such as lockout, auth failed, etc.
if (mSize == SIZE_SMALL) {
@@ -281,6 +352,12 @@
}
@Override
+ public void onAuthenticationFailed(String message) {
+ super.onAuthenticationFailed(message);
+ showTryAgainButton(true);
+ }
+
+ @Override
public void showTryAgainButton(boolean show) {
if (show && mSize == SIZE_SMALL) {
// Do not call super, we will nicely animate the alpha together with the rest
@@ -296,8 +373,6 @@
if (show) {
mPositiveButton.setVisibility(View.GONE);
- } else if (!show && requiresConfirmation()) {
- mPositiveButton.setVisibility(View.VISIBLE);
}
}
@@ -321,27 +396,74 @@
}
@Override
- protected boolean shouldAnimateForTransition(int oldState, int newState) {
- if (oldState == STATE_ERROR && newState == STATE_IDLE) {
- return true;
- } else if (oldState == STATE_IDLE && newState == STATE_AUTHENTICATING) {
- return false;
- } else if (oldState == STATE_AUTHENTICATING && newState == STATE_ERROR) {
- return true;
- } else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATING) {
- return true;
- } else if (oldState == STATE_AUTHENTICATING && newState == STATE_PENDING_CONFIRMATION) {
- return true;
+ protected void updateIcon(int oldState, int newState) {
+ mIconController.mState = newState;
+
+ if (newState == STATE_AUTHENTICATING) {
+ mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
+ if (mDialogAnimatedIn) {
+ mIconController.startPulsing();
+ mErrorText.setVisibility(View.VISIBLE);
+ } else {
+ mIconController.showIcon(R.drawable.face_dialog_pulse_dark_to_light);
+ }
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_authenticating));
} else if (oldState == STATE_PENDING_CONFIRMATION && newState == STATE_AUTHENTICATED) {
- return true;
- } else if (oldState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) {
- return true;
- } else if (oldState == STATE_ERROR && newState == STATE_PENDING_CONFIRMATION) {
- return true;
+ mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_confirmed));
+ } else if (oldState == STATE_ERROR && newState == STATE_IDLE) {
+ mIconController.animateOnce(R.drawable.face_dialog_error_to_idle);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_idle));
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATED) {
- return true;
+ mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
+ mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_authenticated));
+ } else if (newState == STATE_ERROR) {
+ // It's easier to only check newState and gate showing the animation on the
+ // mErrorToIdleAnimationRunnable as a proxy, than add a ton of extra state. For example,
+ // we may go from error -> error due to configuration change which is valid and we
+ // should show the animation, or we can go from error -> error by receiving repeated
+ // acquire messages in which case we do not want to repeatedly start the animation.
+ if (!mHandler.hasCallbacks(mErrorToIdleAnimationRunnable)) {
+ mIconController.animateOnce(R.drawable.face_dialog_dark_to_error);
+ mHandler.postDelayed(mErrorToIdleAnimationRunnable,
+ BiometricPrompt.HIDE_DIALOG_DELAY);
+ }
+ } else if (oldState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) {
+ mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_authenticated));
+ } else if (newState == STATE_PENDING_CONFIRMATION) {
+ mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
+ mIconController.animateOnce(R.drawable.face_dialog_wink_from_dark);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_authenticated));
+ } else if (newState == STATE_IDLE) {
+ mIconController.showStatic(R.drawable.face_dialog_idle_static);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_idle));
+ } else {
+ Log.w(TAG, "Unknown animation from " + oldState + " -> " + newState);
}
- return false;
+
+ // Note that this must be after the newState == STATE_ERROR check above since this affects
+ // the logic.
+ if (oldState == STATE_ERROR && newState == STATE_ERROR) {
+ // Keep the error icon and text around for a while longer if we keep receiving
+ // STATE_ERROR
+ mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
+ mHandler.postDelayed(mErrorToIdleAnimationRunnable, BiometricPrompt.HIDE_DIALOG_DELAY);
+ }
+ }
+
+ @Override
+ public void onDialogAnimatedIn() {
+ mDialogAnimatedIn = true;
+ mIconController.startPulsing();
}
@Override
@@ -357,33 +479,6 @@
return true;
}
- @Override
- protected Drawable getAnimationForTransition(int oldState, int newState) {
- int iconRes;
- if (oldState == STATE_ERROR && newState == STATE_IDLE) {
- iconRes = R.drawable.face_dialog_error_to_face;
- } else if (oldState == STATE_IDLE && newState == STATE_AUTHENTICATING) {
- iconRes = R.drawable.face_dialog_face_to_error;
- } else if (oldState == STATE_AUTHENTICATING && newState == STATE_ERROR) {
- iconRes = R.drawable.face_dialog_face_to_error;
- } else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATING) {
- iconRes = R.drawable.face_dialog_error_to_face;
- } else if (oldState == STATE_AUTHENTICATING && newState == STATE_PENDING_CONFIRMATION) {
- iconRes = R.drawable.face_dialog_face_gray_to_face_blue;
- } else if (oldState == STATE_PENDING_CONFIRMATION && newState == STATE_AUTHENTICATED) {
- iconRes = R.drawable.face_dialog_face_blue_to_checkmark;
- } else if (oldState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) {
- iconRes = R.drawable.face_dialog_face_gray_to_checkmark;
- } else if (oldState == STATE_ERROR && newState == STATE_PENDING_CONFIRMATION) {
- iconRes = R.drawable.face_dialog_face_gray_to_face_blue;
- } else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATED) {
- iconRes = R.drawable.face_dialog_face_blue_to_checkmark;
- } else {
- return null;
- }
- return mContext.getDrawable(iconRes);
- }
-
private float dpToPixels(float dp) {
return dp * ((float) mContext.getResources().getDisplayMetrics().densityDpi
/ DisplayMetrics.DENSITY_DEFAULT);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java
index 412da14..183933e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java
@@ -17,7 +17,9 @@
package com.android.systemui.biometrics;
import android.content.Context;
+import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
+import android.util.Log;
import com.android.systemui.R;
@@ -28,13 +30,15 @@
*/
public class FingerprintDialogView extends BiometricDialogView {
+ private static final String TAG = "FingerprintDialogView";
+
public FingerprintDialogView(Context context,
DialogViewCallback callback) {
super(context, callback);
}
@Override
- protected void handleClearMessage(boolean requireTryAgain) {
+ protected void handleResetMessage() {
updateState(STATE_AUTHENTICATING);
mErrorText.setText(getHintStringResourceId());
mErrorText.setTextColor(mTextColor);
@@ -56,10 +60,27 @@
}
@Override
+ protected void updateIcon(int lastState, int newState) {
+ final Drawable icon = getAnimationForTransition(lastState, newState);
+ if (icon == null) {
+ Log.e(TAG, "Animation not found, " + lastState + " -> " + newState);
+ return;
+ }
+
+ final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
+ ? (AnimatedVectorDrawable) icon
+ : null;
+
+ mBiometricIcon.setImageDrawable(icon);
+
+ if (animation != null && shouldAnimateForTransition(lastState, newState)) {
+ animation.forceAnimationOnUI();
+ animation.start();
+ }
+ }
+
protected boolean shouldAnimateForTransition(int oldState, int newState) {
- if (oldState == STATE_IDLE && newState == STATE_AUTHENTICATING) {
- return false;
- } else if (oldState == STATE_AUTHENTICATING && newState == STATE_ERROR) {
+ if (newState == STATE_ERROR) {
return true;
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATING) {
return true;
@@ -69,6 +90,8 @@
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATED) {
// TODO(b/77328470): add animation when fingerprint is authenticated
return false;
+ } else if (newState == STATE_AUTHENTICATING) {
+ return false;
}
return false;
}
@@ -84,12 +107,9 @@
return true;
}
- @Override
protected Drawable getAnimationForTransition(int oldState, int newState) {
int iconRes;
- if (oldState == STATE_IDLE && newState == STATE_AUTHENTICATING) {
- iconRes = R.drawable.fingerprint_dialog_fp_to_error;
- } else if (oldState == STATE_AUTHENTICATING && newState == STATE_ERROR) {
+ if (newState == STATE_ERROR) {
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATING) {
iconRes = R.drawable.fingerprint_dialog_error_to_fp;
@@ -99,9 +119,11 @@
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATED) {
// TODO(b/77328470): add animation when fingerprint is authenticated
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
+ } else if (newState == STATE_AUTHENTICATING) {
+ iconRes = R.drawable.fingerprint_dialog_fp_to_error;
} else {
return null;
}
return mContext.getDrawable(iconRes);
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgeRenderer.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgeRenderer.java
index 845b084..74ad0fa 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgeRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgeRenderer.java
@@ -18,12 +18,15 @@
import static android.graphics.Paint.ANTI_ALIAS_FLAG;
import static android.graphics.Paint.FILTER_BITMAP_FLAG;
+import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Log;
+import com.android.systemui.R;
+
// XXX: Mostly opied from launcher code / can we share?
/**
* Contains parameters necessary to draw a badge for an icon (e.g. the size of the badge).
@@ -32,20 +35,31 @@
private static final String TAG = "BadgeRenderer";
- // The badge sizes are defined as percentages of the app icon size.
+ /** The badge sizes are defined as percentages of the app icon size. */
private static final float SIZE_PERCENTAGE = 0.38f;
- // Extra scale down of the dot
+ /** Extra scale down of the dot. */
private static final float DOT_SCALE = 0.6f;
private final float mDotCenterOffset;
private final float mCircleRadius;
private final Paint mCirclePaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG);
- public BadgeRenderer(int iconSizePx) {
- mDotCenterOffset = SIZE_PERCENTAGE * iconSizePx;
- int size = (int) (DOT_SCALE * mDotCenterOffset);
- mCircleRadius = size / 2f;
+ public BadgeRenderer(Context context) {
+ mDotCenterOffset = getDotCenterOffset(context);
+ mCircleRadius = getDotRadius(mDotCenterOffset);
+ }
+
+ /** Space between the center of the dot and the top or left of the bubble stack. */
+ static float getDotCenterOffset(Context context) {
+ final int iconSizePx =
+ context.getResources().getDimensionPixelSize(R.dimen.individual_bubble_size);
+ return SIZE_PERCENTAGE * iconSizePx;
+ }
+
+ static float getDotRadius(float dotCenterOffset) {
+ int size = (int) (DOT_SCALE * dotCenterOffset);
+ return size / 2f;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
index 98f446d..783780f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
@@ -23,6 +23,7 @@
import android.util.AttributeSet;
import android.widget.ImageView;
+import com.android.internal.graphics.ColorUtils;
import com.android.systemui.R;
/**
@@ -56,7 +57,7 @@
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mIconSize = getResources().getDimensionPixelSize(R.dimen.individual_bubble_size);
- mDotRenderer = new BadgeRenderer(mIconSize);
+ mDotRenderer = new BadgeRenderer(getContext());
TypedArray ta = context.obtainStyledAttributes(
new int[] {android.R.attr.colorBackgroundFloating});
@@ -82,6 +83,10 @@
invalidate();
}
+ public boolean getDotPosition() {
+ return mOnLeft;
+ }
+
/**
* Set whether the dot should show or not.
*/
@@ -101,7 +106,7 @@
* The colour to use for the dot.
*/
public void setDotColor(int color) {
- mUpdateDotColor = color;
+ mUpdateDotColor = ColorUtils.setAlphaComponent(color, 255 /* alpha */);
invalidate();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 7094d28..8aad0f8 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -46,7 +46,7 @@
private long mLastUpdated;
private long mLastAccessed;
- private static String groupId(NotificationEntry entry) {
+ public static String groupId(NotificationEntry entry) {
UserHandle user = entry.notification.getUser();
return user.getIdentifier() + "|" + entry.notification.getPackageName();
}
@@ -83,7 +83,7 @@
public void updateDotVisibility() {
if (iconView != null) {
- iconView.updateDotVisibility();
+ iconView.updateDotVisibility(true /* animate */);
}
}
@@ -120,11 +120,28 @@
}
}
+ /**
+ * @return the newer of {@link #getLastUpdateTime()} and {@link #getLastAccessTime()}
+ */
public long getLastActivity() {
return Math.max(mLastUpdated, mLastAccessed);
}
/**
+ * @return the timestamp in milliseconds of the most recent notification entry for this bubble
+ */
+ public long getLastUpdateTime() {
+ return mLastUpdated;
+ }
+
+ /**
+ * @return the timestamp in milliseconds when this bubble was last displayed in expanded state
+ */
+ public long getLastAccessTime() {
+ return mLastAccessed;
+ }
+
+ /**
* Should be invoked whenever a Bubble is accessed (selected while expanded).
*/
void markAsAccessedAt(long lastAccessedMillis) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index d071363..48edf67 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -16,6 +16,10 @@
package com.android.systemui.bubbles;
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.View.INVISIBLE;
@@ -23,8 +27,11 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
-import static com.android.systemui.statusbar.notification.NotificationAlertingManager.alertAgain;
+import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
+import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.Nullable;
@@ -53,13 +60,13 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
@@ -69,6 +76,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController;
import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
import java.util.List;
import javax.inject.Inject;
@@ -84,11 +92,12 @@
public class BubbleController implements ConfigurationController.ConfigurationListener {
private static final String TAG = "BubbleController";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
@Retention(SOURCE)
@IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED,
DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION, DISMISS_NO_LONGER_BUBBLE})
+ @Target({FIELD, LOCAL_VARIABLE, PARAMETER})
@interface DismissReason {}
static final int DISMISS_USER_GESTURE = 1;
@@ -99,7 +108,7 @@
static final int DISMISS_ACCESSIBILITY_ACTION = 6;
static final int DISMISS_NO_LONGER_BUBBLE = 7;
- static final int MAX_BUBBLES = 5; // TODO: actually enforce this
+ public static final int MAX_BUBBLES = 5; // TODO: actually enforce this
// Enables some subset of notifs to automatically become bubbles
private static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
@@ -210,6 +219,7 @@
mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
mNotificationEntryManager.addNotificationEntryListener(mEntryListener);
+ mNotificationEntryManager.setNotificationRemoveInterceptor(mRemoveInterceptor);
mStatusBarWindowController = statusBarWindowController;
mStatusBarStateListener = new StatusBarStateListener();
@@ -389,6 +399,46 @@
}
@SuppressWarnings("FieldCanBeLocal")
+ private final NotificationRemoveInterceptor mRemoveInterceptor =
+ new NotificationRemoveInterceptor() {
+ @Override
+ public boolean onNotificationRemoveRequested(String key, int reason) {
+ if (!mBubbleData.hasBubbleWithKey(key)) {
+ return false;
+ }
+ NotificationEntry entry = mBubbleData.getBubbleWithKey(key).entry;
+
+ final boolean isClearAll = reason == REASON_CANCEL_ALL;
+ final boolean isUserDimiss = reason == REASON_CANCEL;
+ final boolean isAppCancel = reason == REASON_APP_CANCEL
+ || reason == REASON_APP_CANCEL_ALL;
+
+ // Need to check for !appCancel here because the notification may have
+ // previously been dismissed & entry.isRowDismissed would still be true
+ boolean userRemovedNotif = (entry.isRowDismissed() && !isAppCancel)
+ || isClearAll || isUserDimiss;
+
+ // The bubble notification sticks around in the data as long as the bubble is
+ // not dismissed and the app hasn't cancelled the notification.
+ boolean bubbleExtended = entry.isBubble() && !entry.isBubbleDismissed()
+ && userRemovedNotif;
+ if (bubbleExtended) {
+ entry.setShowInShadeWhenBubble(false);
+ if (mStackView != null) {
+ mStackView.updateDotVisibility(entry.key);
+ }
+ mNotificationEntryManager.updateNotifications();
+ return true;
+ } else if (!userRemovedNotif && !entry.isBubbleDismissed()) {
+ // This wasn't a user removal so we should remove the bubble as well
+ mBubbleData.notificationEntryRemoved(entry, DISMISS_NOTIF_CANCEL);
+ return false;
+ }
+ return false;
+ }
+ };
+
+ @SuppressWarnings("FieldCanBeLocal")
private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
@Override
public void onPendingEntryAdded(NotificationEntry entry) {
@@ -396,7 +446,6 @@
return;
}
if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) {
- // TODO: handle group summaries?
updateShowInShadeForSuppressNotification(entry);
}
}
@@ -420,29 +469,12 @@
if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.key)) {
// It was previously a bubble but no longer a bubble -- lets remove it
removeBubble(entry.key, DISMISS_NO_LONGER_BUBBLE);
- } else if (shouldBubble && alertAgain(entry, entry.notification.getNotification())) {
+ } else if (shouldBubble) {
updateShowInShadeForSuppressNotification(entry);
entry.setBubbleDismissed(false); // updates come back as bubbles even if dismissed
updateBubble(entry);
}
}
-
- @Override
- public void onEntryRemoved(NotificationEntry entry,
- @Nullable NotificationVisibility visibility,
- boolean removedByUser) {
- if (!areBubblesEnabled(mContext)) {
- return;
- }
- entry.setShowInShadeWhenBubble(false);
- if (mStackView != null) {
- mStackView.updateDotVisibility(entry.key);
- }
- if (!removedByUser) {
- // This was a cancel so we should remove the bubble
- removeBubble(entry.key, DISMISS_NOTIF_CANCEL);
- }
- }
};
@SuppressWarnings("FieldCanBeLocal")
@@ -455,13 +487,15 @@
}
@Override
- public void onBubbleRemoved(Bubble bubble, int reason) {
+ public void onBubbleRemoved(Bubble bubble, @DismissReason int reason) {
if (mStackView != null) {
mStackView.removeBubble(bubble);
}
- if (!bubble.entry.showInShadeWhenBubble()) {
- // The notification is gone & bubble is gone, time to actually remove it
- mNotificationEntryManager.performRemoveNotification(bubble.entry.notification);
+ if (!mBubbleData.hasBubbleWithKey(bubble.getKey())
+ && !bubble.entry.showInShadeWhenBubble()) {
+ // The bubble is gone & the notification is gone, time to actually remove it
+ mNotificationEntryManager.performRemoveNotification(bubble.entry.notification,
+ UNDEFINED_DISMISS_REASON);
} else {
// The notification is still in the shade but we've removed the bubble so
// lets make sure NoMan knows it's not a bubble anymore
@@ -481,6 +515,9 @@
@Override
public void onOrderChanged(List<Bubble> bubbles) {
+ if (mStackView != null) {
+ mStackView.updateBubbleOrder(bubbles);
+ }
}
@Override
@@ -498,13 +535,6 @@
}
@Override
- public void showFlyoutText(Bubble bubble, String text) {
- if (mStackView != null) {
- mStackView.animateInFlyoutForBubble(bubble);
- }
- }
-
- @Override
public void apply() {
mNotificationEntryManager.updateNotifications();
updateVisibility();
@@ -690,6 +720,13 @@
mBubbleData.setExpanded(false);
}
}
+
+ @Override
+ public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
+ if (mStackView != null && taskInfo.displayId == getExpandedDisplayId(mContext)) {
+ mBubbleData.setExpanded(false);
+ }
+ }
}
private static boolean shouldAutoBubbleMessages(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 38ba91e..9156e06 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -23,6 +23,7 @@
import android.app.PendingIntent;
import android.content.Context;
import android.util.Log;
+import android.util.Pair;
import androidx.annotation.Nullable;
@@ -53,10 +54,10 @@
private static final int MAX_BUBBLES = 5;
- private static final Comparator<Bubble> BUBBLES_BY_LAST_ACTIVITY_DESCENDING =
- Comparator.comparing(Bubble::getLastActivity).reversed();
+ private static final Comparator<Bubble> BUBBLES_BY_SORT_KEY_DESCENDING =
+ Comparator.comparing(BubbleData::sortKey).reversed();
- private static final Comparator<Map.Entry<String, Long>> GROUPS_BY_LAST_ACTIVITY_DESCENDING =
+ private static final Comparator<Map.Entry<String, Long>> GROUPS_BY_MAX_SORT_KEY_DESCENDING =
Comparator.<Map.Entry<String, Long>, Long>comparing(Map.Entry::getValue).reversed();
/**
@@ -105,9 +106,6 @@
*/
void onExpandedChanged(boolean expanded);
- /** Flyout text should animate in, showing the given text. */
- void showFlyoutText(Bubble bubble, String text);
-
/** Commit any pending operations (since last call of apply()) */
void apply();
}
@@ -121,15 +119,19 @@
private Bubble mSelectedBubble;
private boolean mExpanded;
- // TODO: ensure this is invalidated at the appropriate time
- private int mSelectedBubbleExpandedPosition = -1;
+ // State tracked during an operation -- keeps track of what listener events to dispatch.
+ private boolean mExpandedChanged;
+ private boolean mOrderChanged;
+ private boolean mSelectionChanged;
+ private Bubble mUpdatedBubble;
+ private Bubble mAddedBubble;
+ private final List<Pair<Bubble, Integer>> mRemovedBubbles = new ArrayList<>();
private TimeSource mTimeSource = System::currentTimeMillis;
@Nullable
private Listener mListener;
- @VisibleForTesting
@Inject
public BubbleData(Context context) {
mContext = context;
@@ -154,18 +156,19 @@
}
public void setExpanded(boolean expanded) {
- if (setExpandedInternal(expanded)) {
- dispatchApply();
+ if (DEBUG) {
+ Log.d(TAG, "setExpanded: " + expanded);
}
+ setExpandedInternal(expanded);
+ dispatchPendingChanges();
}
public void setSelectedBubble(Bubble bubble) {
if (DEBUG) {
Log.d(TAG, "setSelectedBubble: " + bubble);
}
- if (setSelectedBubbleInternal(bubble)) {
- dispatchApply();
- }
+ setSelectedBubbleInternal(bubble);
+ dispatchPendingChanges();
}
public void notificationEntryUpdated(NotificationEntry entry) {
@@ -177,12 +180,12 @@
// Create a new bubble
bubble = new Bubble(entry, this::onBubbleBlocked);
doAdd(bubble);
- dispatchOnBubbleAdded(bubble);
+ trim();
} else {
// Updates an existing bubble
bubble.setEntry(entry);
doUpdate(bubble);
- dispatchOnBubbleUpdated(bubble);
+ mUpdatedBubble = bubble;
}
if (shouldAutoExpand(entry)) {
setSelectedBubbleInternal(bubble);
@@ -192,7 +195,15 @@
} else if (mSelectedBubble == null) {
setSelectedBubbleInternal(bubble);
}
- dispatchApply();
+ dispatchPendingChanges();
+ }
+
+ public void notificationEntryRemoved(NotificationEntry entry, @DismissReason int reason) {
+ if (DEBUG) {
+ Log.d(TAG, "notificationEntryRemoved: entry=" + entry + " reason=" + reason);
+ }
+ doRemove(entry.key, reason);
+ dispatchPendingChanges();
}
private void doAdd(Bubble bubble) {
@@ -202,14 +213,21 @@
int minInsertPoint = 0;
boolean newGroup = !hasBubbleWithGroupId(bubble.getGroupId());
if (isExpanded()) {
- // first bubble of a group goes to the end, otherwise it goes within the existing group
- minInsertPoint =
- newGroup ? mBubbles.size() : findFirstIndexForGroup(bubble.getGroupId());
+ // first bubble of a group goes to the beginning, otherwise within the existing group
+ minInsertPoint = newGroup ? 0 : findFirstIndexForGroup(bubble.getGroupId());
}
- insertBubble(minInsertPoint, bubble);
+ if (insertBubble(minInsertPoint, bubble) < mBubbles.size() - 1) {
+ mOrderChanged = true;
+ }
+ mAddedBubble = bubble;
if (!isExpanded()) {
- packGroup(findFirstIndexForGroup(bubble.getGroupId()));
+ mOrderChanged |= packGroup(findFirstIndexForGroup(bubble.getGroupId()));
+ // Top bubble becomes selected.
+ setSelectedBubbleInternal(mBubbles.get(0));
}
+ }
+
+ private void trim() {
if (mBubbles.size() > MAX_BUBBLES) {
mBubbles.stream()
// sort oldest first (ascending lastActivity)
@@ -217,10 +235,7 @@
// skip the selected bubble
.filter((b) -> !b.equals(mSelectedBubble))
.findFirst()
- .ifPresent((b) -> {
- doRemove(b.getKey(), BubbleController.DISMISS_AGED);
- dispatchApply();
- });
+ .ifPresent((b) -> doRemove(b.getKey(), BubbleController.DISMISS_AGED));
}
}
@@ -229,43 +244,48 @@
Log.d(TAG, "doUpdate: " + bubble);
}
if (!isExpanded()) {
- // while collapsed, update causes re-sort
+ // while collapsed, update causes re-pack
+ int prevPos = mBubbles.indexOf(bubble);
mBubbles.remove(bubble);
- insertBubble(0, bubble);
- packGroup(findFirstIndexForGroup(bubble.getGroupId()));
+ int newPos = insertBubble(0, bubble);
+ if (prevPos != newPos) {
+ packGroup(newPos);
+ mOrderChanged = true;
+ }
+ setSelectedBubbleInternal(mBubbles.get(0));
}
}
- public void notificationEntryRemoved(NotificationEntry entry, @DismissReason int reason) {
- if (DEBUG) {
- Log.d(TAG, "notificationEntryRemoved: entry=" + entry + " reason=" + reason);
- }
- doRemove(entry.key, reason);
- dispatchApply();
- }
-
private void doRemove(String key, @DismissReason int reason) {
int indexToRemove = indexForKey(key);
- if (indexToRemove >= 0) {
- Bubble bubbleToRemove = mBubbles.get(indexToRemove);
- if (mBubbles.size() == 1) {
- // Going to become empty, handle specially.
- setExpandedInternal(false);
- setSelectedBubbleInternal(null);
- }
- mBubbles.remove(indexToRemove);
- dispatchOnBubbleRemoved(bubbleToRemove, reason);
-
- // Note: If mBubbles.isEmpty(), then mSelectedBubble is now null.
- if (Objects.equals(mSelectedBubble, bubbleToRemove)) {
- // Move selection to the new bubble at the same position.
- int newIndex = Math.min(indexToRemove, mBubbles.size() - 1);
- Bubble newSelected = mBubbles.get(newIndex);
- setSelectedBubbleInternal(newSelected);
- }
- bubbleToRemove.setDismissed();
- maybeSendDeleteIntent(reason, bubbleToRemove.entry);
+ if (indexToRemove == -1) {
+ return;
}
+ Bubble bubbleToRemove = mBubbles.get(indexToRemove);
+ if (mBubbles.size() == 1) {
+ // Going to become empty, handle specially.
+ setExpandedInternal(false);
+ setSelectedBubbleInternal(null);
+ }
+ if (indexToRemove < mBubbles.size() - 1) {
+ // Removing anything but the last bubble means positions will change.
+ mOrderChanged = true;
+ }
+ mBubbles.remove(indexToRemove);
+ mRemovedBubbles.add(Pair.create(bubbleToRemove, reason));
+ if (!isExpanded()) {
+ mOrderChanged |= repackAll();
+ }
+
+ // Note: If mBubbles.isEmpty(), then mSelectedBubble is now null.
+ if (Objects.equals(mSelectedBubble, bubbleToRemove)) {
+ // Move selection to the new bubble at the same position.
+ int newIndex = Math.min(indexToRemove, mBubbles.size() - 1);
+ Bubble newSelected = mBubbles.get(newIndex);
+ setSelectedBubbleInternal(newSelected);
+ }
+ bubbleToRemove.setDismissed();
+ maybeSendDeleteIntent(reason, bubbleToRemove.entry);
}
public void dismissAll(@DismissReason int reason) {
@@ -281,87 +301,98 @@
Bubble bubble = mBubbles.remove(0);
bubble.setDismissed();
maybeSendDeleteIntent(reason, bubble.entry);
- dispatchOnBubbleRemoved(bubble, reason);
+ mRemovedBubbles.add(Pair.create(bubble, reason));
}
- dispatchApply();
+ dispatchPendingChanges();
}
- private void dispatchApply() {
- if (mListener != null) {
+
+ private void dispatchPendingChanges() {
+ if (mListener == null) {
+ mExpandedChanged = false;
+ mAddedBubble = null;
+ mSelectionChanged = false;
+ mRemovedBubbles.clear();
+ mUpdatedBubble = null;
+ mOrderChanged = false;
+ return;
+ }
+ boolean anythingChanged = false;
+
+ if (mAddedBubble != null) {
+ mListener.onBubbleAdded(mAddedBubble);
+ mAddedBubble = null;
+ anythingChanged = true;
+ }
+
+ // Compat workaround: Always collapse first.
+ if (mExpandedChanged && !mExpanded) {
+ mListener.onExpandedChanged(mExpanded);
+ mExpandedChanged = false;
+ anythingChanged = true;
+ }
+
+ if (mSelectionChanged) {
+ mListener.onSelectionChanged(mSelectedBubble);
+ mSelectionChanged = false;
+ anythingChanged = true;
+ }
+
+ if (!mRemovedBubbles.isEmpty()) {
+ for (Pair<Bubble, Integer> removed : mRemovedBubbles) {
+ mListener.onBubbleRemoved(removed.first, removed.second);
+ }
+ mRemovedBubbles.clear();
+ anythingChanged = true;
+ }
+
+ if (mUpdatedBubble != null) {
+ mListener.onBubbleUpdated(mUpdatedBubble);
+ mUpdatedBubble = null;
+ anythingChanged = true;
+ }
+
+ if (mOrderChanged) {
+ mListener.onOrderChanged(mBubbles);
+ mOrderChanged = false;
+ anythingChanged = true;
+ }
+
+ if (mExpandedChanged) {
+ mListener.onExpandedChanged(mExpanded);
+ mExpandedChanged = false;
+ anythingChanged = true;
+ }
+
+ if (anythingChanged) {
mListener.apply();
}
}
- private void dispatchOnBubbleAdded(Bubble bubble) {
- if (mListener != null) {
- mListener.onBubbleAdded(bubble);
- }
- }
-
- private void dispatchOnBubbleRemoved(Bubble bubble, @DismissReason int reason) {
- if (mListener != null) {
- mListener.onBubbleRemoved(bubble, reason);
- }
- }
-
- private void dispatchOnExpandedChanged(boolean expanded) {
- if (mListener != null) {
- mListener.onExpandedChanged(expanded);
- }
- }
-
- private void dispatchOnSelectionChanged(@Nullable Bubble bubble) {
- if (mListener != null) {
- mListener.onSelectionChanged(bubble);
- }
- }
-
- private void dispatchOnBubbleUpdated(Bubble bubble) {
- if (mListener != null) {
- mListener.onBubbleUpdated(bubble);
- }
- }
-
- private void dispatchOnOrderChanged(List<Bubble> bubbles) {
- if (mListener != null) {
- mListener.onOrderChanged(bubbles);
- }
- }
-
- private void dispatchShowFlyoutText(Bubble bubble, String text) {
- if (mListener != null) {
- mListener.showFlyoutText(bubble, text);
- }
- }
-
/**
* Requests a change to the selected bubble. Calls {@link Listener#onSelectionChanged} if
* the value changes.
*
* @param bubble the new selected bubble
- * @return true if the state changed as a result
*/
- private boolean setSelectedBubbleInternal(@Nullable Bubble bubble) {
+ private void setSelectedBubbleInternal(@Nullable Bubble bubble) {
if (DEBUG) {
Log.d(TAG, "setSelectedBubbleInternal: " + bubble);
}
if (Objects.equals(bubble, mSelectedBubble)) {
- return false;
+ return;
}
if (bubble != null && !mBubbles.contains(bubble)) {
Log.e(TAG, "Cannot select bubble which doesn't exist!"
+ " (" + bubble + ") bubbles=" + mBubbles);
- return false;
+ return;
}
if (mExpanded && bubble != null) {
- mSelectedBubble.markAsAccessedAt(mTimeSource.currentTimeMillis());
+ bubble.markAsAccessedAt(mTimeSource.currentTimeMillis());
}
mSelectedBubble = bubble;
- dispatchOnSelectionChanged(mSelectedBubble);
- if (!mExpanded || mSelectedBubble == null) {
- mSelectedBubbleExpandedPosition = -1;
- }
- return true;
+ mSelectionChanged = true;
+ return;
}
/**
@@ -369,37 +400,53 @@
* the value changes.
*
* @param shouldExpand the new requested state
- * @return true if the state changed as a result
*/
- private boolean setExpandedInternal(boolean shouldExpand) {
+ private void setExpandedInternal(boolean shouldExpand) {
if (DEBUG) {
Log.d(TAG, "setExpandedInternal: shouldExpand=" + shouldExpand);
}
if (mExpanded == shouldExpand) {
- return false;
- }
- if (mSelectedBubble != null) {
- mSelectedBubble.markAsAccessedAt(mTimeSource.currentTimeMillis());
+ return;
}
if (shouldExpand) {
if (mBubbles.isEmpty()) {
Log.e(TAG, "Attempt to expand stack when empty!");
- return false;
+ return;
}
if (mSelectedBubble == null) {
Log.e(TAG, "Attempt to expand stack without selected bubble!");
- return false;
+ return;
}
- } else {
- repackAll();
+ mSelectedBubble.markAsAccessedAt(mTimeSource.currentTimeMillis());
+ mOrderChanged |= repackAll();
+ } else if (!mBubbles.isEmpty()) {
+ // Apply ordering and grouping rules from expanded -> collapsed, then save
+ // the result.
+ mOrderChanged |= repackAll();
+ // Save the state which should be returned to when expanded (with no other changes)
+
+ if (mBubbles.indexOf(mSelectedBubble) > 0) {
+ // Move the selected bubble to the top while collapsed.
+ if (!mSelectedBubble.isOngoing() && mBubbles.get(0).isOngoing()) {
+ // The selected bubble cannot be raised to the first position because
+ // there is an ongoing bubble there. Instead, force the top ongoing bubble
+ // to become selected.
+ setSelectedBubbleInternal(mBubbles.get(0));
+ } else {
+ // Raise the selected bubble (and it's group) up to the front so the selected
+ // bubble remains on top.
+ mBubbles.remove(mSelectedBubble);
+ mBubbles.add(0, mSelectedBubble);
+ packGroup(0);
+ }
+ }
}
mExpanded = shouldExpand;
- dispatchOnExpandedChanged(mExpanded);
- return true;
+ mExpandedChanged = true;
}
private static long sortKey(Bubble bubble) {
- long key = bubble.getLastActivity();
+ long key = bubble.getLastUpdateTime();
if (bubble.isOngoing()) {
// Set 2nd highest bit (signed long int), to partition between ongoing and regular
key |= 0x4000000000000000L;
@@ -456,8 +503,9 @@
* unchanged. Relative order of any other bubbles are also unchanged.
*
* @param position the position of the first bubble for the group
+ * @return true if the position of any bubbles has changed as a result
*/
- private void packGroup(int position) {
+ private boolean packGroup(int position) {
if (DEBUG) {
Log.d(TAG, "packGroup: position=" + position);
}
@@ -471,16 +519,27 @@
moving.add(0, mBubbles.get(i));
}
}
+ if (moving.isEmpty()) {
+ return false;
+ }
mBubbles.removeAll(moving);
mBubbles.addAll(position + 1, moving);
+ return true;
}
- private void repackAll() {
+ /**
+ * This applies a full sort and group pass to all existing bubbles. The bubbles are grouped
+ * by groupId. Each group is then sorted by the max(lastUpdated) time of it's bubbles. Bubbles
+ * within each group are then sorted by lastUpdated descending.
+ *
+ * @return true if the position of any bubbles changed as a result
+ */
+ private boolean repackAll() {
if (DEBUG) {
Log.d(TAG, "repackAll()");
}
if (mBubbles.isEmpty()) {
- return;
+ return false;
}
Map<String, Long> groupLastActivity = new HashMap<>();
for (Bubble bubble : mBubbles) {
@@ -494,7 +553,7 @@
// Sort groups by their most recently active bubble
List<String> groupsByMostRecentActivity =
groupLastActivity.entrySet().stream()
- .sorted(GROUPS_BY_LAST_ACTIVITY_DESCENDING)
+ .sorted(GROUPS_BY_MAX_SORT_KEY_DESCENDING)
.map(Map.Entry::getKey)
.collect(toList());
@@ -504,10 +563,14 @@
for (String appId : groupsByMostRecentActivity) {
mBubbles.stream()
.filter((b) -> b.getGroupId().equals(appId))
- .sorted(BUBBLES_BY_LAST_ACTIVITY_DESCENDING)
+ .sorted(BUBBLES_BY_SORT_KEY_DESCENDING)
.forEachOrdered(repacked::add);
}
+ if (repacked.equals(mBubbles)) {
+ return false;
+ }
mBubbles = repacked;
+ return true;
}
private void maybeSendDeleteIntent(@DismissReason int reason, NotificationEntry entry) {
@@ -527,21 +590,25 @@
}
private void onBubbleBlocked(NotificationEntry entry) {
- boolean changed = false;
- final String blockedPackage = entry.notification.getPackageName();
+ final String blockedGroupId = Bubble.groupId(entry);
+ int selectedIndex = mBubbles.indexOf(mSelectedBubble);
for (Iterator<Bubble> i = mBubbles.iterator(); i.hasNext(); ) {
Bubble bubble = i.next();
- if (bubble.getPackageName().equals(blockedPackage)) {
+ if (bubble.getGroupId().equals(blockedGroupId)) {
+ mRemovedBubbles.add(Pair.create(bubble, BubbleController.DISMISS_BLOCKED));
i.remove();
- // TODO: handle removal of selected bubble, and collapse safely if emptied (see
- // dismissAll)
- dispatchOnBubbleRemoved(bubble, BubbleController.DISMISS_BLOCKED);
- changed = true;
}
}
- if (changed) {
- dispatchApply();
+ if (mBubbles.isEmpty()) {
+ setExpandedInternal(false);
+ setSelectedBubbleInternal(null);
+ } else if (!mBubbles.contains(mSelectedBubble)) {
+ // choose a new one
+ int newIndex = Math.min(selectedIndex, mBubbles.size() - 1);
+ Bubble newSelected = mBubbles.get(newIndex);
+ setSelectedBubbleInternal(newSelected);
}
+ dispatchPendingChanges();
}
private int indexForKey(String key) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDismissView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDismissView.java
new file mode 100644
index 0000000..4db1e27
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDismissView.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.bubbles;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.dynamicanimation.animation.DynamicAnimation;
+import androidx.dynamicanimation.animation.SpringAnimation;
+import androidx.dynamicanimation.animation.SpringForce;
+
+import com.android.systemui.R;
+
+/** Dismiss view that contains a scrim gradient, as well as a dismiss icon, text, and circle. */
+public class BubbleDismissView extends FrameLayout {
+ /** Duration for animations involving the dismiss target text/icon/gradient. */
+ private static final int DISMISS_TARGET_ANIMATION_BASE_DURATION = 150;
+
+ private View mDismissGradient;
+
+ private LinearLayout mDismissTarget;
+ private ImageView mDismissIcon;
+ private TextView mDismissText;
+ private View mDismissCircle;
+
+ private SpringAnimation mDismissTargetAlphaSpring;
+ private SpringAnimation mDismissTargetVerticalSpring;
+
+ public BubbleDismissView(Context context) {
+ super(context);
+ setVisibility(GONE);
+
+ mDismissGradient = new FrameLayout(mContext);
+
+ FrameLayout.LayoutParams gradientParams =
+ new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
+ gradientParams.gravity = Gravity.BOTTOM;
+ mDismissGradient.setLayoutParams(gradientParams);
+
+ Drawable gradient = mContext.getResources().getDrawable(R.drawable.pip_dismiss_scrim);
+ gradient.setAlpha((int) (255 * 0.85f));
+ mDismissGradient.setBackground(gradient);
+
+ mDismissGradient.setVisibility(GONE);
+ addView(mDismissGradient);
+
+ LayoutInflater.from(context).inflate(R.layout.bubble_dismiss_target, this, true);
+ mDismissTarget = findViewById(R.id.bubble_dismiss_icon_container);
+ mDismissIcon = findViewById(R.id.bubble_dismiss_close_icon);
+ mDismissText = findViewById(R.id.bubble_dismiss_text);
+ mDismissCircle = findViewById(R.id.bubble_dismiss_circle);
+
+ // Set up the basic target area animations. These are very simple animations that don't need
+ // fancy interpolators.
+ final AccelerateDecelerateInterpolator interpolator =
+ new AccelerateDecelerateInterpolator();
+ mDismissGradient.animate()
+ .setDuration(DISMISS_TARGET_ANIMATION_BASE_DURATION)
+ .setInterpolator(interpolator);
+ mDismissText.animate()
+ .setDuration(DISMISS_TARGET_ANIMATION_BASE_DURATION)
+ .setInterpolator(interpolator);
+ mDismissIcon.animate()
+ .setDuration(DISMISS_TARGET_ANIMATION_BASE_DURATION)
+ .setInterpolator(interpolator);
+ mDismissCircle.animate()
+ .setDuration(DISMISS_TARGET_ANIMATION_BASE_DURATION / 2)
+ .setInterpolator(interpolator);
+
+ mDismissTargetAlphaSpring =
+ new SpringAnimation(mDismissTarget, DynamicAnimation.ALPHA)
+ .setSpring(new SpringForce()
+ .setStiffness(SpringForce.STIFFNESS_LOW)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));
+ mDismissTargetVerticalSpring =
+ new SpringAnimation(mDismissTarget, DynamicAnimation.TRANSLATION_Y)
+ .setSpring(new SpringForce()
+ .setStiffness(SpringForce.STIFFNESS_MEDIUM)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));
+
+ mDismissTargetAlphaSpring.addEndListener((anim, canceled, alpha, velocity) -> {
+ // Since DynamicAnimations end when they're 'nearly' done, we can't rely on alpha being
+ // exactly zero when this listener is triggered. However, if it's less than 50% we can
+ // safely assume it was animating out rather than in.
+ if (alpha < 0.5f) {
+ // If the alpha spring was animating the view out, set it to GONE when it's done.
+ setVisibility(GONE);
+ }
+ });
+ }
+
+ /** Springs in the dismiss target and fades in the gradient. */
+ void springIn() {
+ setVisibility(View.VISIBLE);
+
+ // Fade in the dismiss target (icon + text).
+ mDismissTarget.setAlpha(0f);
+ mDismissTargetAlphaSpring.animateToFinalPosition(1f);
+
+ // Spring up the dismiss target (icon + text).
+ mDismissTarget.setTranslationY(mDismissTarget.getHeight() / 2f);
+ mDismissTargetVerticalSpring.animateToFinalPosition(0);
+
+ // Fade in the gradient.
+ mDismissGradient.setVisibility(VISIBLE);
+ mDismissGradient.animate().alpha(1f);
+
+ // Make sure the dismiss elements are in the separated position (in case we hid the target
+ // while they were condensed to cover the bubbles being in the target).
+ mDismissIcon.setAlpha(1f);
+ mDismissIcon.setScaleX(1f);
+ mDismissIcon.setScaleY(1f);
+ mDismissIcon.setTranslationX(0f);
+ mDismissText.setAlpha(1f);
+ mDismissText.setTranslationX(0f);
+ }
+
+ /** Springs out the dismiss target and fades out the gradient. */
+ void springOut() {
+ // Fade out the target.
+ mDismissTargetAlphaSpring.animateToFinalPosition(0f);
+
+ // Spring the target down a bit.
+ mDismissTargetVerticalSpring.animateToFinalPosition(mDismissTarget.getHeight() / 2f);
+
+ // Fade out the gradient and then set it to GONE so it's not in the SBV hierarchy.
+ mDismissGradient.animate().alpha(0f).withEndAction(
+ () -> mDismissGradient.setVisibility(GONE));
+
+ // Pop out the dismiss circle.
+ mDismissCircle.animate().alpha(0f).scaleX(1.2f).scaleY(1.2f);
+ }
+
+ /**
+ * Encircles the center of the dismiss target, pulling the X towards the center and hiding the
+ * text.
+ */
+ void animateEncircleCenterWithX(boolean encircle) {
+ // Pull the text towards the center if we're encircling (it'll be faded out, leaving only
+ // the X icon over the bubbles), or back to normal if we're un-encircling.
+ final float textTranslation = encircle
+ ? -mDismissIcon.getWidth() / 4f
+ : 0f;
+
+ // Center the icon if we're encircling, or put it back to normal if not.
+ final float iconTranslation = encircle
+ ? mDismissTarget.getWidth() / 2f
+ - mDismissIcon.getWidth() / 2f
+ - mDismissIcon.getLeft()
+ : 0f;
+
+ // Fade in/out the text and translate it.
+ mDismissText.animate()
+ .alpha(encircle ? 0f : 1f)
+ .translationX(textTranslation);
+
+ mDismissIcon.animate()
+ .setDuration(150)
+ .translationX(iconTranslation);
+
+ // Fade out the gradient if we're encircling (the bubbles will 'absorb' it by darkening
+ // themselves).
+ mDismissGradient.animate()
+ .alpha(encircle ? 0f : 1f);
+
+ // Prepare the circle to be 'dropped in'.
+ if (encircle) {
+ mDismissCircle.setAlpha(0f);
+ mDismissCircle.setScaleX(1.2f);
+ mDismissCircle.setScaleY(1.2f);
+ }
+
+ // Drop in the circle, or pull it back up.
+ mDismissCircle.animate()
+ .alpha(encircle ? 1f : 0f)
+ .scaleX(encircle ? 1f : 0f)
+ .scaleY(encircle ? 1f : 0f);
+ }
+
+ /** Animates the circle and the centered icon out. */
+ void animateEncirclingCircleDisappearance() {
+ // Pop out the dismiss icon and circle.
+ mDismissIcon.animate()
+ .setDuration(50)
+ .scaleX(0.9f)
+ .scaleY(0.9f)
+ .alpha(0f);
+ mDismissCircle.animate()
+ .scaleX(0.9f)
+ .scaleY(0.9f)
+ .alpha(0f);
+ }
+
+ /** Returns the Y value of the center of the dismiss target. */
+ float getDismissTargetCenterY() {
+ return getTop() + mDismissTarget.getTop() + mDismissTarget.getHeight() / 2f;
+ }
+
+ /** Returns the dismiss target, which contains the text/icon and any added padding. */
+ View getDismissTarget() {
+ return mDismissTarget;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 67f3274..39867c3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -22,8 +22,6 @@
import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS;
import static android.view.Display.INVALID_DISPLAY;
-import android.animation.LayoutTransition;
-import android.animation.ObjectAnimator;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.ActivityView;
@@ -41,9 +39,7 @@
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.ShapeDrawable;
-import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
@@ -54,13 +50,9 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.TextView;
import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.TriangleShape;
import com.android.systemui.statusbar.AlphaOptimizedButton;
@@ -80,10 +72,6 @@
private AlphaOptimizedButton mSettingsIcon;
- // Permission view
- private View mPermissionView;
- private TextView mPermissionPrompt;
-
// Views for expanded state
private ExpandableNotificationRow mNotifRow;
private ActivityView mActivityView;
@@ -97,7 +85,6 @@
private int mMinHeight;
private int mSettingsIconHeight;
private int mBubbleHeight;
- private int mPermissionHeight;
private int mPointerWidth;
private int mPointerHeight;
@@ -194,36 +181,11 @@
triangleDrawable.setTint(bgColor);
mPointerView.setBackground(triangleDrawable);
- FrameLayout permissionOrSettings = findViewById(R.id.permission_or_settings);
-
- LayoutTransition transition = new LayoutTransition();
- transition.setDuration(200);
-
- ObjectAnimator appearAnimator = ObjectAnimator.ofFloat(null, View.ALPHA, 0f, 1f);
- transition.setAnimator(LayoutTransition.APPEARING, appearAnimator);
- transition.setInterpolator(LayoutTransition.APPEARING, Interpolators.ALPHA_IN);
-
- ObjectAnimator disappearAnimator = ObjectAnimator.ofFloat(null, View.ALPHA, 1f, 0f);
- transition.setAnimator(LayoutTransition.DISAPPEARING, disappearAnimator);
- transition.setInterpolator(LayoutTransition.DISAPPEARING, Interpolators.ALPHA_OUT);
-
- transition.setAnimateParentHierarchy(false);
- permissionOrSettings.setLayoutTransition(transition);
- permissionOrSettings.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
-
mSettingsIconHeight = getContext().getResources().getDimensionPixelSize(
R.dimen.bubble_expanded_header_height);
mSettingsIcon = findViewById(R.id.settings_button);
mSettingsIcon.setOnClickListener(this);
- mPermissionHeight = getContext().getResources().getDimensionPixelSize(
- R.dimen.bubble_permission_height);
- mPermissionView = findViewById(R.id.permission_layout);
- mPermissionPrompt = mPermissionView.findViewById(R.id.prompt);
-
- findViewById(R.id.no_bubbles_button).setOnClickListener(this);
- findViewById(R.id.yes_bubbles_button).setOnClickListener(this);
-
mActivityView = new ActivityView(mContext, null /* attrs */, 0 /* defStyle */,
true /* singleTaskInstance */);
addView(mActivityView);
@@ -273,23 +235,6 @@
}
/**
- * Creates a background with corners rounded based on how the view is configured to display
- */
- private Drawable createPermissionBackground(int bgColor) {
- TypedArray ta2 = getContext().obtainStyledAttributes(
- new int[] {android.R.attr.dialogCornerRadius});
- final float cr = ta2.getDimension(0, 0f);
- ta2.recycle();
-
- float[] radii = new float[] {cr, cr, cr, cr, 0, 0, 0, 0};
- GradientDrawable chromeBackground = new GradientDrawable();
- chromeBackground.setShape(GradientDrawable.RECTANGLE);
- chromeBackground.setCornerRadii(radii);
- chromeBackground.setColor(bgColor);
- return chromeBackground;
- }
-
- /**
* Sets the listener to notify when a bubble has been blocked.
*/
public void setOnBlockedListener(OnBubbleBlockedListener listener) {
@@ -323,7 +268,7 @@
mAppIcon = mPm.getDefaultActivityIcon();
}
updateTheme();
- togglePermissionOrSettings();
+ showSettingsIcon();
updateExpandedView();
}
@@ -370,10 +315,6 @@
int foregroundColor = ta.getColor(1, Color.BLACK /* default */);
ta.recycle();
- // Update permission prompt color.
- mPermissionView.setBackground(createPermissionBackground(backgroundColor));
- mPermissionPrompt.setTextColor(foregroundColor);
-
// Update triangle color.
ShapeDrawable triangleDrawable = new ShapeDrawable(
TriangleShape.create(mPointerWidth, mPointerHeight, false /* pointUp */));
@@ -381,22 +322,6 @@
mPointerView.setBackground(triangleDrawable);
}
- void togglePermissionOrSettings() {
- boolean hasUserApprovedBubblesForPackage = false;
- try {
- hasUserApprovedBubblesForPackage =
- mNotificationManagerService.hasUserApprovedBubblesForPackage(
- mEntry.notification.getPackageName(), mEntry.notification.getUid());
- } catch (RemoteException e) {
- Log.w(TAG, e);
- }
- if (hasUserApprovedBubblesForPackage) {
- showSettingsIcon();
- } else {
- showPermissionView();
- }
- }
-
private void updateExpandedView() {
mBubbleIntent = getBubbleIntent(mEntry);
if (mBubbleIntent != null) {
@@ -427,11 +352,8 @@
* @return total height that the expanded view occupies.
*/
int getExpandedSize() {
- int chromeHeight = mPermissionView.getVisibility() != View.VISIBLE
- ? mSettingsIconHeight
- : mPermissionHeight;
return mBubbleHeight + mPointerView.getHeight() + mPointerMargin
- + chromeHeight;
+ + mSettingsIconHeight;
}
void updateHeight() {
@@ -455,11 +377,8 @@
}
desiredHeight = desiredPx > 0 ? desiredPx : mMinHeight;
}
- int chromeHeight = mPermissionView.getVisibility() != View.VISIBLE
- ? mSettingsIconHeight
- : mPermissionHeight;
- int max = mStackView.getMaxExpandedHeight() - chromeHeight - mPointerView.getHeight()
- - mPointerMargin;
+ int max = mStackView.getMaxExpandedHeight() - mSettingsIconHeight
+ - mPointerView.getHeight() - mPointerMargin;
float height = Math.min(desiredHeight, max);
height = Math.max(height, mMinHeight);
LayoutParams lp = (LayoutParams) mActivityView.getLayoutParams();
@@ -492,30 +411,6 @@
logBubbleClickEvent(mEntry,
StatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS);
});
- } else if (id == R.id.no_bubbles_button) {
- setBubblesAllowed(false);
- } else if (id == R.id.yes_bubbles_button) {
- setBubblesAllowed(true);
- }
- }
-
- private void setBubblesAllowed(boolean allowed) {
- try {
- mNotificationManagerService.setBubblesAllowed(
- mEntry.notification.getPackageName(),
- mEntry.notification.getUid(),
- allowed);
- if (allowed) {
- showSettingsIcon();
- } else if (mOnBubbleBlockedListener != null) {
- mOnBubbleBlockedListener.onBubbleBlocked(mEntry);
- }
- mStackView.onExpandedHeightChanged();
- logBubbleClickEvent(mEntry,
- allowed ? StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_OPT_IN :
- StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_OPT_OUT);
- } catch (RemoteException e) {
- Log.w(TAG, e);
}
}
@@ -526,23 +421,9 @@
void showSettingsIcon() {
updateSettingsContentDescription();
-
- mPermissionView.setVisibility(GONE);
mSettingsIcon.setVisibility(VISIBLE);
}
- void showPermissionView() {
- ((ImageView) mPermissionView.findViewById(R.id.pkgicon)).setImageDrawable(mAppIcon);
- ((TextView) mPermissionView.findViewById(R.id.pkgname)).setText(mAppName);
- mPermissionPrompt.setText(
- getResources().getString(R.string.bubbles_prompt, mAppName));
- logBubbleClickEvent(mEntry,
- StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_DIALOG_SHOWN);
-
- mSettingsIcon.setVisibility(GONE);
- mPermissionView.setVisibility(VISIBLE);
- }
-
/**
* Update appearance of the expanded view being displayed.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
new file mode 100644
index 0000000..71f68c1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.bubbles;
+
+import static android.graphics.Paint.ANTI_ALIAS_FLAG;
+import static android.graphics.Paint.FILTER_BITMAP_FLAG;
+
+import android.animation.ArgbEvaluator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Outline;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.graphics.drawable.ShapeDrawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import androidx.dynamicanimation.animation.DynamicAnimation;
+import androidx.dynamicanimation.animation.SpringAnimation;
+
+import com.android.systemui.R;
+import com.android.systemui.recents.TriangleShape;
+
+/**
+ * Flyout view that appears as a 'chat bubble' alongside the bubble stack. The flyout can visually
+ * transform into the 'new' dot, which is used during flyout dismiss animations/gestures.
+ */
+public class BubbleFlyoutView extends FrameLayout {
+ /** Max width of the flyout, in terms of percent of the screen width. */
+ private static final float FLYOUT_MAX_WIDTH_PERCENT = .6f;
+
+ private final int mFlyoutPadding;
+ private final int mFlyoutSpaceFromBubble;
+ private final int mPointerSize;
+ private final int mBubbleSize;
+ private final int mFlyoutElevation;
+ private final int mBubbleElevation;
+ private final int mFloatingBackgroundColor;
+ private final float mCornerRadius;
+
+ private final ViewGroup mFlyoutTextContainer;
+ private final TextView mFlyoutText;
+ /** Spring animation for the flyout. */
+ private final SpringAnimation mFlyoutSpring =
+ new SpringAnimation(this, DynamicAnimation.TRANSLATION_X);
+
+ /** Values related to the 'new' dot which we use to figure out where to collapse the flyout. */
+ private final float mNewDotRadius;
+ private final float mNewDotSize;
+ private final float mNewDotOffsetFromBubbleBounds;
+
+ /**
+ * The paint used to draw the background, whose color changes as the flyout transitions to the
+ * tinted 'new' dot.
+ */
+ private final Paint mBgPaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG);
+ private final ArgbEvaluator mArgbEvaluator = new ArgbEvaluator();
+
+ /**
+ * Triangular ShapeDrawables used for the triangle that points from the flyout to the bubble
+ * stack (a chat-bubble effect).
+ */
+ private final ShapeDrawable mLeftTriangleShape;
+ private final ShapeDrawable mRightTriangleShape;
+
+ /** Whether the flyout arrow is on the left (pointing left) or right (pointing right). */
+ private boolean mArrowPointingLeft = true;
+
+ /** Color of the 'new' dot that the flyout will transform into. */
+ private int mDotColor;
+
+ /** The outline of the triangle, used for elevation shadows. */
+ private final Outline mTriangleOutline = new Outline();
+
+ /** The bounds of the flyout background, kept up to date as it transitions to the 'new' dot. */
+ private final RectF mBgRect = new RectF();
+
+ /**
+ * Percent progress in the transition from flyout to 'new' dot. These two values are the inverse
+ * of each other (if we're 40% transitioned to the dot, we're 60% flyout), but it makes the code
+ * much more readable.
+ */
+ private float mPercentTransitionedToDot = 1f;
+ private float mPercentStillFlyout = 0f;
+
+ /**
+ * The difference in values between the flyout and the dot. These differences are gradually
+ * added over the course of the animation to transform the flyout into the 'new' dot.
+ */
+ private float mFlyoutToDotWidthDelta = 0f;
+ private float mFlyoutToDotHeightDelta = 0f;
+ private float mFlyoutToDotCornerRadiusDelta;
+
+ /** The translation values when the flyout is completely transitioned into the dot. */
+ private float mTranslationXWhenDot = 0f;
+ private float mTranslationYWhenDot = 0f;
+
+ /**
+ * The current translation values applied to the flyout background as it transitions into the
+ * 'new' dot.
+ */
+ private float mBgTranslationX;
+ private float mBgTranslationY;
+
+ /** The flyout's X translation when at rest (not animating or dragging). */
+ private float mRestingTranslationX = 0f;
+
+ /** Callback to run when the flyout is hidden. */
+ private Runnable mOnHide;
+
+ public BubbleFlyoutView(Context context) {
+ super(context);
+ LayoutInflater.from(context).inflate(R.layout.bubble_flyout, this, true);
+
+ mFlyoutTextContainer = findViewById(R.id.bubble_flyout_text_container);
+ mFlyoutText = mFlyoutTextContainer.findViewById(R.id.bubble_flyout_text);
+
+ final Resources res = getResources();
+ mFlyoutPadding = res.getDimensionPixelSize(R.dimen.bubble_flyout_padding_x);
+ mFlyoutSpaceFromBubble = res.getDimensionPixelSize(R.dimen.bubble_flyout_space_from_bubble);
+ mPointerSize = res.getDimensionPixelSize(R.dimen.bubble_flyout_pointer_size);
+ mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
+ mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
+ mFlyoutElevation = res.getDimensionPixelSize(R.dimen.bubble_flyout_elevation);
+ mNewDotOffsetFromBubbleBounds = BadgeRenderer.getDotCenterOffset(context);
+ mNewDotRadius = BadgeRenderer.getDotRadius(mNewDotOffsetFromBubbleBounds);
+ mNewDotSize = mNewDotRadius * 2f;
+
+ final TypedArray ta = mContext.obtainStyledAttributes(
+ new int[] {
+ android.R.attr.colorBackgroundFloating,
+ android.R.attr.dialogCornerRadius});
+ mFloatingBackgroundColor = ta.getColor(0, Color.WHITE);
+ mCornerRadius = ta.getDimensionPixelSize(1, 0);
+ mFlyoutToDotCornerRadiusDelta = mNewDotRadius - mCornerRadius;
+ ta.recycle();
+
+ // Add padding for the pointer on either side, onDraw will draw it in this space.
+ setPadding(mPointerSize, 0, mPointerSize, 0);
+ setWillNotDraw(false);
+ setClipChildren(false);
+ setTranslationZ(mFlyoutElevation);
+ setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ BubbleFlyoutView.this.getOutline(outline);
+ }
+ });
+
+ mBgPaint.setColor(mFloatingBackgroundColor);
+
+ mLeftTriangleShape =
+ new ShapeDrawable(TriangleShape.createHorizontal(
+ mPointerSize, mPointerSize, true /* isPointingLeft */));
+ mLeftTriangleShape.setBounds(0, 0, mPointerSize, mPointerSize);
+ mLeftTriangleShape.getPaint().setColor(mFloatingBackgroundColor);
+
+ mRightTriangleShape =
+ new ShapeDrawable(TriangleShape.createHorizontal(
+ mPointerSize, mPointerSize, false /* isPointingLeft */));
+ mRightTriangleShape.setBounds(0, 0, mPointerSize, mPointerSize);
+ mRightTriangleShape.getPaint().setColor(mFloatingBackgroundColor);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ renderBackground(canvas);
+ invalidateOutline();
+ super.onDraw(canvas);
+ }
+
+ /** Configures the flyout and animates it in. */
+ void showFlyout(
+ CharSequence updateMessage, PointF stackPos, float parentWidth,
+ boolean arrowPointingLeft, int dotColor, Runnable onHide) {
+ mArrowPointingLeft = arrowPointingLeft;
+ mDotColor = dotColor;
+ mOnHide = onHide;
+
+ setCollapsePercent(0f);
+ setAlpha(0f);
+ setVisibility(VISIBLE);
+
+ // Set the flyout TextView's max width in terms of percent, and then subtract out the
+ // padding so that the entire flyout view will be the desired width (rather than the
+ // TextView being the desired width + extra padding).
+ mFlyoutText.setMaxWidth(
+ (int) (parentWidth * FLYOUT_MAX_WIDTH_PERCENT) - mFlyoutPadding * 2);
+ mFlyoutText.setText(updateMessage);
+
+ // Wait for the TextView to lay out so we know its line count.
+ post(() -> {
+ // Multi line flyouts get top-aligned to the bubble.
+ if (mFlyoutText.getLineCount() > 1) {
+ setTranslationY(stackPos.y);
+ } else {
+ // Single line flyouts are vertically centered with respect to the bubble.
+ setTranslationY(
+ stackPos.y + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f);
+ }
+
+ // Calculate the translation required to position the flyout next to the bubble stack,
+ // with the desired padding.
+ mRestingTranslationX = mArrowPointingLeft
+ ? stackPos.x + mBubbleSize + mFlyoutSpaceFromBubble
+ : stackPos.x - getWidth() - mFlyoutSpaceFromBubble;
+
+ // Translate towards the stack slightly.
+ setTranslationX(
+ mRestingTranslationX + (arrowPointingLeft ? -mBubbleSize : mBubbleSize));
+
+ // Fade in the entire flyout and spring it to its normal position.
+ animate().alpha(1f);
+ mFlyoutSpring.animateToFinalPosition(mRestingTranslationX);
+
+ // Calculate the difference in size between the flyout and the 'dot' so that we can
+ // transform into the dot later.
+ mFlyoutToDotWidthDelta = getWidth() - mNewDotSize;
+ mFlyoutToDotHeightDelta = getHeight() - mNewDotSize;
+
+ // Calculate the translation values needed to be in the correct 'new dot' position.
+ final float distanceFromFlyoutLeftToDotCenterX =
+ mFlyoutSpaceFromBubble + mNewDotOffsetFromBubbleBounds / 2;
+ if (mArrowPointingLeft) {
+ mTranslationXWhenDot = -distanceFromFlyoutLeftToDotCenterX - mNewDotRadius;
+ } else {
+ mTranslationXWhenDot =
+ getWidth() + distanceFromFlyoutLeftToDotCenterX - mNewDotRadius;
+ }
+
+ mTranslationYWhenDot =
+ getHeight() / 2f
+ - mNewDotRadius
+ - mBubbleSize / 2f
+ + mNewDotOffsetFromBubbleBounds / 2;
+ });
+ }
+
+ /**
+ * Hides the flyout and runs the optional callback passed into showFlyout. The flyout has been
+ * animated into the 'new' dot by the time we call this, so no animations are needed.
+ */
+ void hideFlyout() {
+ if (mOnHide != null) {
+ mOnHide.run();
+ mOnHide = null;
+ }
+
+ setVisibility(GONE);
+ }
+
+ /** Sets the percentage that the flyout should be collapsed into dot form. */
+ void setCollapsePercent(float percentCollapsed) {
+ mPercentTransitionedToDot = Math.max(0f, Math.min(percentCollapsed, 1f));
+ mPercentStillFlyout = (1f - mPercentTransitionedToDot);
+
+ // Move and fade out the text.
+ mFlyoutText.setTranslationX(
+ (mArrowPointingLeft ? -getWidth() : getWidth()) * mPercentTransitionedToDot);
+ mFlyoutText.setAlpha(clampPercentage(
+ (mPercentStillFlyout - (1f - BubbleStackView.FLYOUT_DRAG_PERCENT_DISMISS))
+ / BubbleStackView.FLYOUT_DRAG_PERCENT_DISMISS));
+
+ // Reduce the elevation towards that of the topmost bubble.
+ setTranslationZ(
+ mFlyoutElevation
+ - (mFlyoutElevation - mBubbleElevation) * mPercentTransitionedToDot);
+ invalidate();
+ }
+
+ /** Return the flyout's resting X translation (translation when not dragging or animating). */
+ float getRestingTranslationX() {
+ return mRestingTranslationX;
+ }
+
+ /** Clamps a float to between 0 and 1. */
+ private float clampPercentage(float percent) {
+ return Math.min(1f, Math.max(0f, percent));
+ }
+
+ /**
+ * Renders the background, which is either the rounded 'chat bubble' flyout, or some state
+ * between that and the 'new' dot over the bubbles.
+ */
+ private void renderBackground(Canvas canvas) {
+ // Calculate the width, height, and corner radius of the flyout given the current collapsed
+ // percentage.
+ final float width = getWidth() - (mFlyoutToDotWidthDelta * mPercentTransitionedToDot);
+ final float height = getHeight() - (mFlyoutToDotHeightDelta * mPercentTransitionedToDot);
+ final float cornerRadius = mCornerRadius
+ - (mFlyoutToDotCornerRadiusDelta * mPercentTransitionedToDot);
+
+ // Translate the flyout background towards the collapsed 'dot' state.
+ mBgTranslationX = mTranslationXWhenDot * mPercentTransitionedToDot;
+ mBgTranslationY = mTranslationYWhenDot * mPercentTransitionedToDot;
+
+ // Set the bounds of the rounded rectangle that serves as either the flyout background or
+ // the collapsed 'dot'. These bounds will also be used to provide the outline for elevation
+ // shadows. In the expanded flyout state, the left and right bounds leave space for the
+ // pointer triangle - as the flyout collapses, this space is reduced since the triangle
+ // retracts into the flyout.
+ mBgRect.set(
+ mPointerSize * mPercentStillFlyout /* left */,
+ 0 /* top */,
+ width - mPointerSize * mPercentStillFlyout /* right */,
+ height /* bottom */);
+
+ mBgPaint.setColor(
+ (int) mArgbEvaluator.evaluate(
+ mPercentTransitionedToDot, mFloatingBackgroundColor, mDotColor));
+
+ canvas.save();
+ canvas.translate(mBgTranslationX, mBgTranslationY);
+ renderPointerTriangle(canvas, width, height);
+ canvas.drawRoundRect(mBgRect, cornerRadius, cornerRadius, mBgPaint);
+ canvas.restore();
+ }
+
+ /** Renders the 'pointer' triangle that points from the flyout to the bubble stack. */
+ private void renderPointerTriangle(
+ Canvas canvas, float currentFlyoutWidth, float currentFlyoutHeight) {
+ canvas.save();
+
+ // Translation to apply for the 'retraction' effect as the flyout collapses.
+ final float retractionTranslationX =
+ (mArrowPointingLeft ? 1 : -1) * (mPercentTransitionedToDot * mPointerSize * 2f);
+
+ // Place the arrow either at the left side, or the far right, depending on whether the
+ // flyout is on the left or right side.
+ final float arrowTranslationX =
+ mArrowPointingLeft
+ ? retractionTranslationX
+ : currentFlyoutWidth - mPointerSize + retractionTranslationX;
+
+ // Vertically center the arrow at all times.
+ final float arrowTranslationY = currentFlyoutHeight / 2f - mPointerSize / 2f;
+
+ // Draw the appropriate direction of arrow.
+ final ShapeDrawable relevantTriangle =
+ mArrowPointingLeft ? mLeftTriangleShape : mRightTriangleShape;
+ canvas.translate(arrowTranslationX, arrowTranslationY);
+ relevantTriangle.setAlpha((int) (255f * mPercentStillFlyout));
+ relevantTriangle.draw(canvas);
+
+ // Save the triangle's outline for use in the outline provider, offsetting it to reflect its
+ // current position.
+ relevantTriangle.getOutline(mTriangleOutline);
+ mTriangleOutline.offset((int) arrowTranslationX, (int) arrowTranslationY);
+
+ canvas.restore();
+ }
+
+ /** Builds an outline that includes the transformed flyout background and triangle. */
+ private void getOutline(Outline outline) {
+ if (!mTriangleOutline.isEmpty()) {
+ // Draw the rect into the outline as a path so we can merge the triangle path into it.
+ final Path rectPath = new Path();
+ rectPath.addRoundRect(mBgRect, mCornerRadius, mCornerRadius, Path.Direction.CW);
+ outline.setConvexPath(rectPath);
+
+ // Get rid of the triangle path once it has disappeared behind the flyout.
+ if (mPercentStillFlyout > 0.5f) {
+ outline.mPath.addPath(mTriangleOutline.mPath);
+ }
+
+ // Translate the outline to match the background's position.
+ final Matrix outlineMatrix = new Matrix();
+ outlineMatrix.postTranslate(getLeft() + mBgTranslationX, getTop() + mBgTranslationY);
+
+ // At the very end, retract the outline into the bubble so the shadow will be pulled
+ // into the flyout-dot as it (visually) becomes part of the bubble. We can't do this by
+ // animating translationZ to zero since then it'll go under the bubbles, which have
+ // elevation.
+ if (mPercentTransitionedToDot > 0.98f) {
+ final float percentBetween99and100 = (mPercentTransitionedToDot - 0.98f) / .02f;
+ final float percentShadowVisible = 1f - percentBetween99and100;
+
+ // Keep it centered.
+ outlineMatrix.postTranslate(
+ mNewDotRadius * percentBetween99and100,
+ mNewDotRadius * percentBetween99and100);
+ outlineMatrix.preScale(percentShadowVisible, percentShadowVisible);
+ }
+
+ outline.mPath.transform(outlineMatrix);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index d1bc9a9..4fef157 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -19,19 +19,23 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.content.Context;
import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
import android.graphics.Outline;
+import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.ShapeDrawable;
import android.os.Bundle;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.util.StatsLog;
@@ -45,13 +49,14 @@
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.FrameLayout;
-import android.widget.TextView;
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.DynamicAnimation;
+import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
@@ -61,7 +66,6 @@
import com.android.systemui.bubbles.animation.ExpandedAnimationController;
import com.android.systemui.bubbles.animation.PhysicsAnimationLayout;
import com.android.systemui.bubbles.animation.StackAnimationController;
-import com.android.systemui.recents.TriangleShape;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.math.BigDecimal;
@@ -77,11 +81,23 @@
private static final String TAG = "BubbleStackView";
private static final boolean DEBUG = false;
+ /** How far the flyout needs to be dragged before it's dismissed regardless of velocity. */
+ static final float FLYOUT_DRAG_PERCENT_DISMISS = 0.25f;
+
+ /** Velocity required to dismiss the flyout via drag. */
+ private static final float FLYOUT_DISMISS_VELOCITY = 2000f;
+
+ /**
+ * Factor for attenuating translation when the flyout is overscrolled (8f = flyout moves 1 pixel
+ * for every 8 pixels overscrolled).
+ */
+ private static final float FLYOUT_OVERSCROLL_ATTENUATION_FACTOR = 8f;
+
/** Duration of the flyout alpha animations. */
private static final int FLYOUT_ALPHA_ANIMATION_DURATION = 100;
- /** Max width of the flyout, in terms of percent of the screen width. */
- private static final float FLYOUT_MAX_WIDTH_PERCENT = .6f;
+ /** Percent to darken the bubbles when they're in the dismiss target. */
+ private static final float DARKEN_PERCENT = 0.3f;
/** How long to wait, in milliseconds, before hiding the flyout. */
@VisibleForTesting
@@ -130,23 +146,19 @@
private final SpringAnimation mExpandedViewYAnim;
private final BubbleData mBubbleData;
+ private final Vibrator mVibrator;
+ private final ValueAnimator mDesaturateAndDarkenAnimator;
+ private final Paint mDesaturateAndDarkenPaint = new Paint();
+
private PhysicsAnimationLayout mBubbleContainer;
private StackAnimationController mStackAnimationController;
private ExpandedAnimationController mExpandedAnimationController;
private FrameLayout mExpandedViewContainer;
- private FrameLayout mFlyoutContainer;
- private FrameLayout mFlyout;
- private TextView mFlyoutText;
- private ShapeDrawable mLeftFlyoutTriangle;
- private ShapeDrawable mRightFlyoutTriangle;
- /** Spring animation for the flyout. */
- private SpringAnimation mFlyoutSpring;
+ private BubbleFlyoutView mFlyout;
/** Runnable that fades out the flyout and then sets it to GONE. */
- private Runnable mHideFlyout =
- () -> mFlyoutContainer.animate().alpha(0f).withEndAction(
- () -> mFlyoutContainer.setVisibility(GONE));
+ private Runnable mHideFlyout = () -> animateFlyoutCollapsed(true, 0 /* velX */);
/** Layout change listener that moves the stack to the nearest valid position on rotation. */
private OnLayoutChangeListener mMoveStackToValidPositionOnLayoutListener;
@@ -160,9 +172,6 @@
private int mBubbleSize;
private int mBubblePadding;
- private int mFlyoutPadding;
- private int mFlyoutSpaceFromBubble;
- private int mPointerSize;
private int mExpandedAnimateXDistance;
private int mExpandedAnimateYDistance;
private int mStatusBarHeight;
@@ -173,8 +182,11 @@
private boolean mIsExpanded;
private boolean mImeVisible;
- /** Whether the stack is currently being dragged. */
- private boolean mIsDragging = false;
+ /** Whether the stack is currently on the left side of the screen, or animating there. */
+ private boolean mStackOnLeftOrWillBe = false;
+
+ /** Whether a touch gesture, such as a stack/bubble drag or flyout drag, is in progress. */
+ private boolean mIsGestureInProgress = false;
private BubbleTouchHandler mTouchHandler;
private BubbleController.BubbleExpandListener mExpandListener;
@@ -182,6 +194,20 @@
private boolean mViewUpdatedRequested = false;
private boolean mIsExpansionAnimating = false;
+ private boolean mShowingDismiss = false;
+
+ /**
+ * Whether the user is currently dragging their finger within the dismiss target. In this state
+ * the stack will be magnetized to the center of the target, so we shouldn't move it until the
+ * touch exits the dismiss target area.
+ */
+ private boolean mDraggingInDismissTarget = false;
+
+ /** Whether the stack is magneting towards the dismiss target. */
+ private boolean mAnimatingMagnet = false;
+
+ /** The view to desaturate/darken when magneted to the dismiss target. */
+ private View mDesaturateAndDarkenTargetView;
private LayoutInflater mInflater;
@@ -219,8 +245,44 @@
}
};
+ /** Float property that 'drags' the flyout. */
+ private final FloatPropertyCompat mFlyoutCollapseProperty =
+ new FloatPropertyCompat("FlyoutCollapseSpring") {
+ @Override
+ public float getValue(Object o) {
+ return mFlyoutDragDeltaX;
+ }
+
+ @Override
+ public void setValue(Object o, float v) {
+ onFlyoutDragged(v);
+ }
+ };
+
+ /** SpringAnimation that springs the flyout collapsed via onFlyoutDragged. */
+ private final SpringAnimation mFlyoutTransitionSpring =
+ new SpringAnimation(this, mFlyoutCollapseProperty);
+
+ /** Distance the flyout has been dragged in the X axis. */
+ private float mFlyoutDragDeltaX = 0f;
+
+ /**
+ * End listener for the flyout spring that either posts a runnable to hide the flyout, or hides
+ * it immediately.
+ */
+ private final DynamicAnimation.OnAnimationEndListener mAfterFlyoutTransitionSpring =
+ (dynamicAnimation, b, v, v1) -> {
+ if (mFlyoutDragDeltaX == 0) {
+ mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER);
+ } else {
+ mFlyout.hideFlyout();
+ }
+ };
+
@NonNull private final SurfaceSynchronizer mSurfaceSynchronizer;
+ private BubbleDismissView mDismissContainer;
+ private Runnable mAfterMagnet;
public BubbleStackView(Context context, BubbleData data,
@Nullable SurfaceSynchronizer synchronizer) {
@@ -235,9 +297,6 @@
Resources res = getResources();
mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
mBubblePadding = res.getDimensionPixelSize(R.dimen.bubble_padding);
- mFlyoutPadding = res.getDimensionPixelSize(R.dimen.bubble_flyout_padding_x);
- mFlyoutSpaceFromBubble = res.getDimensionPixelSize(R.dimen.bubble_flyout_space_from_bubble);
- mPointerSize = res.getDimensionPixelSize(R.dimen.bubble_flyout_pointer_size);
mExpandedAnimateXDistance =
res.getDimensionPixelSize(R.dimen.bubble_expanded_animate_x_distance);
mExpandedAnimateYDistance =
@@ -252,6 +311,8 @@
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getSize(mDisplaySize);
+ mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
+
int padding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
@@ -273,17 +334,31 @@
mExpandedViewContainer.setClipChildren(false);
addView(mExpandedViewContainer);
- mFlyoutContainer = (FrameLayout) mInflater.inflate(R.layout.bubble_flyout, this, false);
- mFlyoutContainer.setVisibility(GONE);
- mFlyoutContainer.setClipToPadding(false);
- mFlyoutContainer.setClipChildren(false);
- mFlyoutContainer.animate()
+ mFlyout = new BubbleFlyoutView(context);
+ mFlyout.setVisibility(GONE);
+ mFlyout.animate()
.setDuration(FLYOUT_ALPHA_ANIMATION_DURATION)
.setInterpolator(new AccelerateDecelerateInterpolator());
+ addView(mFlyout, new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
- mFlyout = mFlyoutContainer.findViewById(R.id.bubble_flyout);
- addView(mFlyoutContainer);
- setupFlyout();
+ mFlyoutTransitionSpring.setSpring(new SpringForce()
+ .setStiffness(SpringForce.STIFFNESS_MEDIUM)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));
+ mFlyoutTransitionSpring.addEndListener(mAfterFlyoutTransitionSpring);
+
+ mDismissContainer = new BubbleDismissView(mContext);
+ mDismissContainer.setLayoutParams(new FrameLayout.LayoutParams(
+ MATCH_PARENT,
+ getResources().getDimensionPixelSize(R.dimen.pip_dismiss_gradient_height),
+ Gravity.BOTTOM));
+ addView(mDismissContainer);
+
+ mDismissContainer = new BubbleDismissView(mContext);
+ mDismissContainer.setLayoutParams(new FrameLayout.LayoutParams(
+ MATCH_PARENT,
+ getResources().getDimensionPixelSize(R.dimen.pip_dismiss_gradient_height),
+ Gravity.BOTTOM));
+ addView(mDismissContainer);
mExpandedViewXAnim =
new SpringAnimation(mExpandedViewContainer, DynamicAnimation.TRANSLATION_X);
@@ -341,6 +416,29 @@
// This must be a separate OnDrawListener since it should be called for every draw.
getViewTreeObserver().addOnDrawListener(mSystemGestureExcludeUpdater);
+
+ final ColorMatrix animatedMatrix = new ColorMatrix();
+ final ColorMatrix darkenMatrix = new ColorMatrix();
+
+ mDesaturateAndDarkenAnimator = ValueAnimator.ofFloat(1f, 0f);
+ mDesaturateAndDarkenAnimator.addUpdateListener(animation -> {
+ final float animatedValue = (float) animation.getAnimatedValue();
+ animatedMatrix.setSaturation(animatedValue);
+
+ final float animatedDarkenValue = (1f - animatedValue) * DARKEN_PERCENT;
+ darkenMatrix.setScale(
+ 1f - animatedDarkenValue /* red */,
+ 1f - animatedDarkenValue /* green */,
+ 1f - animatedDarkenValue /* blue */,
+ 1f /* alpha */);
+
+ // Concat the matrices so that the animatedMatrix both desaturates and darkens.
+ animatedMatrix.postConcat(darkenMatrix);
+
+ // Update the paint and apply it to the bubble container.
+ mDesaturateAndDarkenPaint.setColorFilter(new ColorMatrixColorFilter(animatedMatrix));
+ mDesaturateAndDarkenTargetView.setLayerPaint(mDesaturateAndDarkenPaint);
+ });
}
/**
@@ -391,11 +489,34 @@
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfoInternal(info);
- info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
+
+ // Custom actions.
+ AccessibilityAction moveTopLeft = new AccessibilityAction(R.id.action_move_top_left,
+ getContext().getResources()
+ .getString(R.string.bubble_accessibility_action_move_top_left));
+ info.addAction(moveTopLeft);
+
+ AccessibilityAction moveTopRight = new AccessibilityAction(R.id.action_move_top_right,
+ getContext().getResources()
+ .getString(R.string.bubble_accessibility_action_move_top_right));
+ info.addAction(moveTopRight);
+
+ AccessibilityAction moveBottomLeft = new AccessibilityAction(R.id.action_move_bottom_left,
+ getContext().getResources()
+ .getString(R.string.bubble_accessibility_action_move_bottom_left));
+ info.addAction(moveBottomLeft);
+
+ AccessibilityAction moveBottomRight = new AccessibilityAction(R.id.action_move_bottom_right,
+ getContext().getResources()
+ .getString(R.string.bubble_accessibility_action_move_bottom_right));
+ info.addAction(moveBottomRight);
+
+ // Default actions.
+ info.addAction(AccessibilityAction.ACTION_DISMISS);
if (mIsExpanded) {
- info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE);
+ info.addAction(AccessibilityAction.ACTION_COLLAPSE);
} else {
- info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
+ info.addAction(AccessibilityAction.ACTION_EXPAND);
}
}
@@ -404,16 +525,30 @@
if (super.performAccessibilityActionInternal(action, arguments)) {
return true;
}
- switch (action) {
- case AccessibilityNodeInfo.ACTION_DISMISS:
- mBubbleData.dismissAll(BubbleController.DISMISS_ACCESSIBILITY_ACTION);
- return true;
- case AccessibilityNodeInfo.ACTION_COLLAPSE:
- mBubbleData.setExpanded(false);
- return true;
- case AccessibilityNodeInfo.ACTION_EXPAND:
- mBubbleData.setExpanded(true);
- return true;
+ final RectF stackBounds = mStackAnimationController.getAllowableStackPositionRegion();
+
+ // R constants are not final so we cannot use switch-case here.
+ if (action == AccessibilityNodeInfo.ACTION_DISMISS) {
+ mBubbleData.dismissAll(BubbleController.DISMISS_ACCESSIBILITY_ACTION);
+ return true;
+ } else if (action == AccessibilityNodeInfo.ACTION_COLLAPSE) {
+ mBubbleData.setExpanded(false);
+ return true;
+ } else if (action == AccessibilityNodeInfo.ACTION_EXPAND) {
+ mBubbleData.setExpanded(true);
+ return true;
+ } else if (action == R.id.action_move_top_left) {
+ mStackAnimationController.springStack(stackBounds.left, stackBounds.top);
+ return true;
+ } else if (action == R.id.action_move_top_right) {
+ mStackAnimationController.springStack(stackBounds.right, stackBounds.top);
+ return true;
+ } else if (action == R.id.action_move_bottom_left) {
+ mStackAnimationController.springStack(stackBounds.left, stackBounds.bottom);
+ return true;
+ } else if (action == R.id.action_move_bottom_right) {
+ mStackAnimationController.springStack(stackBounds.right, stackBounds.bottom);
+ return true;
}
return false;
}
@@ -511,6 +646,7 @@
mBubbleContainer.addView(bubble.iconView, 0,
new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
ViewClippingUtil.setClippingDeactivated(bubble.iconView, true, mClippingParameters);
+ animateInFlyoutForBubble(bubble);
requestUpdate();
logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__POSTED);
}
@@ -532,10 +668,19 @@
// via BubbleData.Listener
void updateBubble(Bubble bubble) {
+ animateInFlyoutForBubble(bubble);
requestUpdate();
logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__UPDATED);
}
+ public void updateBubbleOrder(List<Bubble> bubbles) {
+ for (int i = 0; i < bubbles.size(); i++) {
+ Bubble bubble = bubbles.get(i);
+ mBubbleContainer.moveViewTo(bubble.iconView, i);
+ }
+ }
+
+
/**
* Changes the currently selected bubble. If the stack is already expanded, the newly selected
* bubble will be shown immediately. This does not change the expanded state or change the
@@ -631,7 +776,7 @@
}
// Outside parts of view we care about.
return null;
- } else if (mFlyoutContainer.getVisibility() == VISIBLE && isIntersecting(mFlyout, x, y)) {
+ } else if (mFlyout.getVisibility() == VISIBLE && isIntersecting(mFlyout, x, y)) {
return mFlyout;
}
@@ -790,23 +935,22 @@
}
mExpandedAnimationController.dragBubbleOut(bubble, x, y);
+ springInDismissTarget();
}
/** Called when a drag operation on an individual bubble has finished. */
public void onBubbleDragFinish(
- View bubble, float x, float y, float velX, float velY, boolean dismissed) {
+ View bubble, float x, float y, float velX, float velY) {
if (DEBUG) {
- Log.d(TAG, "onBubbleDragFinish: bubble=" + bubble + ", dismissed=" + dismissed);
+ Log.d(TAG, "onBubbleDragFinish: bubble=" + bubble);
}
+
if (!mIsExpanded || mIsExpansionAnimating) {
return;
}
- if (dismissed) {
- mExpandedAnimationController.prepareForDismissalWithVelocity(bubble, velX, velY);
- } else {
- mExpandedAnimationController.snapBubbleBack(bubble, velX, velY);
- }
+ mExpandedAnimationController.snapBubbleBack(bubble, velX, velY);
+ springOutDismissTargetAndHideCircle();
}
void onDragStart() {
@@ -821,7 +965,7 @@
mBubbleContainer.setController(mStackAnimationController);
hideFlyoutImmediate();
- mIsDragging = true;
+ mDraggingInDismissTarget = false;
}
void onDragged(float x, float y) {
@@ -829,27 +973,266 @@
return;
}
- mStackAnimationController.moveFirstBubbleWithStackFollowing(x, y);
+ springInDismissTarget();
+ mStackAnimationController.moveStackFromTouch(x, y);
}
void onDragFinish(float x, float y, float velX, float velY) {
if (DEBUG) {
Log.d(TAG, "onDragFinish");
}
- // TODO: Add fling to bottom to dismiss.
- mIsDragging = false;
if (mIsExpanded || mIsExpansionAnimating) {
return;
}
- mStackAnimationController.flingStackThenSpringToEdge(x, velX, velY);
+ final float newStackX = mStackAnimationController.flingStackThenSpringToEdge(x, velX, velY);
logBubbleEvent(null /* no bubble associated with bubble stack move */,
StatsLog.BUBBLE_UICHANGED__ACTION__STACK_MOVED);
+
+ mStackOnLeftOrWillBe = newStackX <= 0;
+ updateBubbleShadowsAndDotPosition(true /* animate */);
+ springOutDismissTargetAndHideCircle();
}
- void onDragFinishAsDismiss() {
- mIsDragging = false;
+ void onFlyoutDragStart() {
+ mFlyout.removeCallbacks(mHideFlyout);
+ }
+
+ void onFlyoutDragged(float deltaX) {
+ final boolean onLeft = mStackAnimationController.isStackOnLeftSide();
+ mFlyoutDragDeltaX = deltaX;
+
+ final float collapsePercent =
+ onLeft ? -deltaX / mFlyout.getWidth() : deltaX / mFlyout.getWidth();
+ mFlyout.setCollapsePercent(Math.min(1f, Math.max(0f, collapsePercent)));
+
+ // Calculate how to translate the flyout if it has been dragged too far in etiher direction.
+ float overscrollTranslation = 0f;
+ if (collapsePercent < 0f || collapsePercent > 1f) {
+ // Whether we are more than 100% transitioned to the dot.
+ final boolean overscrollingPastDot = collapsePercent > 1f;
+
+ // Whether we are overscrolling physically to the left - this can either be pulling the
+ // flyout away from the stack (if the stack is on the right) or pushing it to the left
+ // after it has already become the dot.
+ final boolean overscrollingLeft =
+ (onLeft && collapsePercent > 1f) || (!onLeft && collapsePercent < 0f);
+
+ overscrollTranslation =
+ (overscrollingPastDot ? collapsePercent - 1f : collapsePercent * -1)
+ * (overscrollingLeft ? -1 : 1)
+ * (mFlyout.getWidth() / (FLYOUT_OVERSCROLL_ATTENUATION_FACTOR
+ // Attenuate the smaller dot less than the larger flyout.
+ / (overscrollingPastDot ? 2 : 1)));
+ }
+
+ mFlyout.setTranslationX(mFlyout.getRestingTranslationX() + overscrollTranslation);
+ }
+
+ /**
+ * Called when the flyout drag has finished, and returns true if the gesture successfully
+ * dismissed the flyout.
+ */
+ void onFlyoutDragFinished(float deltaX, float velX) {
+ final boolean onLeft = mStackAnimationController.isStackOnLeftSide();
+ final boolean metRequiredVelocity =
+ onLeft ? velX < -FLYOUT_DISMISS_VELOCITY : velX > FLYOUT_DISMISS_VELOCITY;
+ final boolean metRequiredDeltaX =
+ onLeft
+ ? deltaX < -mFlyout.getWidth() * FLYOUT_DRAG_PERCENT_DISMISS
+ : deltaX > mFlyout.getWidth() * FLYOUT_DRAG_PERCENT_DISMISS;
+ final boolean isCancelFling = onLeft ? velX > 0 : velX < 0;
+ final boolean shouldDismiss = metRequiredVelocity || (metRequiredDeltaX && !isCancelFling);
+
+ mFlyout.removeCallbacks(mHideFlyout);
+ animateFlyoutCollapsed(shouldDismiss, velX);
+ }
+
+ /**
+ * Called when the first touch event of a gesture (stack drag, bubble drag, flyout drag, etc.)
+ * is received.
+ */
+ void onGestureStart() {
+ mIsGestureInProgress = true;
+ }
+
+ /** Called when a gesture is completed or cancelled. */
+ void onGestureFinished() {
+ mIsGestureInProgress = false;
+ }
+
+ /** Prepares and starts the desaturate/darken animation on the bubble stack. */
+ private void animateDesaturateAndDarken(View targetView, boolean desaturateAndDarken) {
+ mDesaturateAndDarkenTargetView = targetView;
+
+ if (desaturateAndDarken) {
+ // Use the animated paint for the bubbles.
+ mDesaturateAndDarkenTargetView.setLayerType(
+ View.LAYER_TYPE_HARDWARE, mDesaturateAndDarkenPaint);
+ mDesaturateAndDarkenAnimator.removeAllListeners();
+ mDesaturateAndDarkenAnimator.start();
+ } else {
+ mDesaturateAndDarkenAnimator.removeAllListeners();
+ mDesaturateAndDarkenAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ // Stop using the animated paint.
+ resetDesaturationAndDarken();
+ }
+ });
+ mDesaturateAndDarkenAnimator.reverse();
+ }
+ }
+
+ private void resetDesaturationAndDarken() {
+ mDesaturateAndDarkenAnimator.removeAllListeners();
+ mDesaturateAndDarkenAnimator.cancel();
+ mDesaturateAndDarkenTargetView.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+
+ /**
+ * Magnets the stack to the target, while also transforming the target to encircle the stack and
+ * desaturating/darkening the bubbles.
+ */
+ void animateMagnetToDismissTarget(
+ View magnetView, boolean toTarget, float x, float y, float velX, float velY) {
+ mDraggingInDismissTarget = toTarget;
+
+ if (toTarget) {
+ // The Y-value for the bubble stack to be positioned in the center of the dismiss target
+ final float destY = mDismissContainer.getDismissTargetCenterY() - mBubbleSize / 2f;
+
+ mAnimatingMagnet = true;
+
+ final Runnable afterMagnet = () -> {
+ mAnimatingMagnet = false;
+ if (mAfterMagnet != null) {
+ mAfterMagnet.run();
+ }
+ };
+
+ if (magnetView == this) {
+ mStackAnimationController.magnetToDismiss(velX, velY, destY, afterMagnet);
+ animateDesaturateAndDarken(mBubbleContainer, true);
+ } else {
+ mExpandedAnimationController.magnetBubbleToDismiss(
+ magnetView, velX, velY, destY, afterMagnet);
+
+ animateDesaturateAndDarken(magnetView, true);
+ }
+
+ mDismissContainer.animateEncircleCenterWithX(true);
+
+ } else {
+ mAnimatingMagnet = false;
+
+ if (magnetView == this) {
+ mStackAnimationController.demagnetizeFromDismissToPoint(x, y, velX, velY);
+ animateDesaturateAndDarken(mBubbleContainer, false);
+ } else {
+ mExpandedAnimationController.demagnetizeBubbleTo(x, y, velX, velY);
+ animateDesaturateAndDarken(magnetView, false);
+ }
+
+ mDismissContainer.animateEncircleCenterWithX(false);
+ }
+
+ mVibrator.vibrate(VibrationEffect.get(toTarget
+ ? VibrationEffect.EFFECT_CLICK
+ : VibrationEffect.EFFECT_TICK));
+ }
+
+ /**
+ * Magnets the stack to the dismiss target if it's not already there. Then, dismiss the stack
+ * using the 'implode' animation and animate out the target.
+ */
+ void magnetToStackIfNeededThenAnimateDismissal(
+ View touchedView, float velX, float velY, Runnable after) {
+ final Runnable animateDismissal = () -> {
+ mAfterMagnet = null;
+
+ mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
+ mDismissContainer.animateEncirclingCircleDisappearance();
+
+ // 'Implode' the stack and then hide the dismiss target.
+ if (touchedView == this) {
+ mStackAnimationController.implodeStack(
+ () -> {
+ mAnimatingMagnet = false;
+ mShowingDismiss = false;
+ mDraggingInDismissTarget = false;
+ after.run();
+ resetDesaturationAndDarken();
+ });
+ } else {
+ mExpandedAnimationController.dismissDraggedOutBubble(() -> {
+ mAnimatingMagnet = false;
+ mShowingDismiss = false;
+ mDraggingInDismissTarget = false;
+ resetDesaturationAndDarken();
+ after.run();
+ });
+ }
+ };
+
+ if (mAnimatingMagnet) {
+ // If the magnet animation is currently playing, dismiss the stack after it's done. This
+ // happens if the stack is flung towards the target.
+ mAfterMagnet = animateDismissal;
+ } else if (mDraggingInDismissTarget) {
+ // If we're in the dismiss target, but not animating, we already magneted - dismiss
+ // immediately.
+ animateDismissal.run();
+ } else {
+ // Otherwise, we need to start the magnet animation and then dismiss afterward.
+ animateMagnetToDismissTarget(touchedView, true, -1 /* x */, -1 /* y */, velX, velY);
+ mAfterMagnet = animateDismissal;
+ }
+ }
+
+ /** Animates in the dismiss target, including the gradient behind it. */
+ private void springInDismissTarget() {
+ if (mShowingDismiss) {
+ return;
+ }
+
+ mShowingDismiss = true;
+
+ // Show the dismiss container and bring it to the front so the bubbles will go behind it.
+ mDismissContainer.springIn();
+ mDismissContainer.bringToFront();
+ mDismissContainer.setZ(Short.MAX_VALUE - 1);
+ }
+
+ /**
+ * Animates the dismiss target out, as well as the circle that encircles the bubbles, if they
+ * were dragged into the target and encircled.
+ */
+ private void springOutDismissTargetAndHideCircle() {
+ if (!mShowingDismiss) {
+ return;
+ }
+
+ mDismissContainer.springOut();
+ mShowingDismiss = false;
+ }
+
+ /** Whether the location of the given MotionEvent is within the dismiss target area. */
+ boolean isInDismissTarget(MotionEvent ev) {
+ return isIntersecting(mDismissContainer.getDismissTarget(), ev.getRawX(), ev.getRawY());
+ }
+
+ /** Animates the flyout collapsed (to dot), or the reverse, starting with the given velocity. */
+ private void animateFlyoutCollapsed(boolean collapsed, float velX) {
+ final boolean onLeft = mStackAnimationController.isStackOnLeftSide();
+ mFlyoutTransitionSpring
+ .setStartValue(mFlyoutDragDeltaX)
+ .setStartVelocity(velX)
+ .animateToFinalPosition(collapsed
+ ? (onLeft ? -mFlyout.getWidth() : mFlyout.getWidth())
+ : 0f);
}
/**
@@ -888,55 +1271,27 @@
final CharSequence updateMessage = bubble.entry.getUpdateMessage(getContext());
// Show the message if one exists, and we're not expanded or animating expansion.
- if (updateMessage != null && !isExpanded() && !mIsExpansionAnimating && !mIsDragging) {
- final PointF stackPos = mStackAnimationController.getStackPosition();
+ if (updateMessage != null
+ && !isExpanded()
+ && !mIsExpansionAnimating
+ && !mIsGestureInProgress) {
+ if (bubble.iconView != null) {
+ bubble.iconView.setSuppressDot(true /* suppressDot */, false /* animate */);
+ mFlyoutDragDeltaX = 0f;
+ mFlyout.setAlpha(0f);
- // Set the flyout TextView's max width in terms of percent, and then subtract out the
- // padding so that the entire flyout view will be the desired width (rather than the
- // TextView being the desired width + extra padding).
- mFlyoutText.setMaxWidth(
- (int) (getWidth() * FLYOUT_MAX_WIDTH_PERCENT) - mFlyoutPadding * 2);
-
- mFlyoutContainer.setAlpha(0f);
- mFlyoutContainer.setVisibility(VISIBLE);
-
- mFlyoutText.setText(updateMessage);
-
- final boolean onLeft = mStackAnimationController.isStackOnLeftSide();
-
- if (onLeft) {
- mLeftFlyoutTriangle.setAlpha(255);
- mRightFlyoutTriangle.setAlpha(0);
- } else {
- mLeftFlyoutTriangle.setAlpha(0);
- mRightFlyoutTriangle.setAlpha(255);
+ // Post in case layout isn't complete and getWidth returns 0.
+ post(() -> mFlyout.showFlyout(
+ updateMessage, mStackAnimationController.getStackPosition(), getWidth(),
+ mStackAnimationController.isStackOnLeftSide(),
+ bubble.iconView.getBadgeColor(),
+ () -> {
+ bubble.iconView.setSuppressDot(
+ false /* suppressDot */, false /* animate */);
+ }));
}
-
- mFlyoutContainer.post(() -> {
- // Multi line flyouts get top-aligned to the bubble.
- if (mFlyoutText.getLineCount() > 1) {
- mFlyoutContainer.setTranslationY(stackPos.y);
- } else {
- // Single line flyouts are vertically centered with respect to the bubble.
- mFlyoutContainer.setTranslationY(
- stackPos.y + (mBubbleSize - mFlyout.getHeight()) / 2f);
- }
-
- final float destinationX = onLeft
- ? stackPos.x + mBubbleSize + mFlyoutSpaceFromBubble
- : stackPos.x - mFlyoutContainer.getWidth() - mFlyoutSpaceFromBubble;
-
- // Translate towards the stack slightly, then spring out from the stack.
- mFlyoutContainer.setTranslationX(
- destinationX + (onLeft ? -mBubblePadding : mBubblePadding));
-
- mFlyoutContainer.animate().alpha(1f);
- mFlyoutSpring.animateToFinalPosition(destinationX);
-
- mFlyout.removeCallbacks(mHideFlyout);
- mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER);
- });
-
+ mFlyout.removeCallbacks(mHideFlyout);
+ mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER);
logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__FLYOUT);
}
}
@@ -944,7 +1299,7 @@
/** Hide the flyout immediately and cancel any pending hide runnables. */
private void hideFlyoutImmediate() {
mFlyout.removeCallbacks(mHideFlyout);
- mHideFlyout.run();
+ mFlyout.hideFlyout();
}
@Override
@@ -957,7 +1312,7 @@
mBubbleContainer.getBoundsOnScreen(outRect);
}
- if (mFlyoutContainer.getVisibility() == View.VISIBLE) {
+ if (mFlyout.getVisibility() == View.VISIBLE) {
final Rect flyoutBounds = new Rect();
mFlyout.getBoundsOnScreen(flyoutBounds);
outRect.union(flyoutBounds);
@@ -1014,78 +1369,11 @@
}
}
- /** Sets up the flyout views and drawables. */
- private void setupFlyout() {
- // Retrieve the styled floating background color.
- TypedArray ta = mContext.obtainStyledAttributes(
- new int[] {android.R.attr.colorBackgroundFloating});
- final int floatingBackgroundColor = ta.getColor(0, Color.WHITE);
- ta.recycle();
-
- // Retrieve the flyout background, which is currently a rounded white rectangle with a
- // shadow but no triangular arrow pointing anywhere.
- final LayerDrawable flyoutBackground = (LayerDrawable) mFlyout.getBackground();
-
- // Create the triangle drawables and set their color.
- mLeftFlyoutTriangle =
- new ShapeDrawable(TriangleShape.createHorizontal(
- mPointerSize, mPointerSize, true /* isPointingLeft */));
- mRightFlyoutTriangle =
- new ShapeDrawable(TriangleShape.createHorizontal(
- mPointerSize, mPointerSize, false /* isPointingLeft */));
- mLeftFlyoutTriangle.getPaint().setColor(floatingBackgroundColor);
- mRightFlyoutTriangle.getPaint().setColor(floatingBackgroundColor);
-
- // Add both triangles to the drawable. We'll show and hide the appropriate ones when we show
- // the flyout.
- final int leftTriangleIndex = flyoutBackground.addLayer(mLeftFlyoutTriangle);
- flyoutBackground.setLayerSize(leftTriangleIndex, mPointerSize, mPointerSize);
- flyoutBackground.setLayerGravity(leftTriangleIndex, Gravity.LEFT | Gravity.CENTER_VERTICAL);
- flyoutBackground.setLayerInsetLeft(leftTriangleIndex, -mPointerSize);
-
- final int rightTriangleIndex = flyoutBackground.addLayer(mRightFlyoutTriangle);
- flyoutBackground.setLayerSize(rightTriangleIndex, mPointerSize, mPointerSize);
- flyoutBackground.setLayerGravity(
- rightTriangleIndex, Gravity.RIGHT | Gravity.CENTER_VERTICAL);
- flyoutBackground.setLayerInsetRight(rightTriangleIndex, -mPointerSize);
-
- // Append the appropriate triangle's outline to the view's outline so that the shadows look
- // correct.
- mFlyout.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- final boolean leftPointing = mStackAnimationController.isStackOnLeftSide();
-
- // Get the outline from the appropriate triangle.
- final Outline triangleOutline = new Outline();
- if (leftPointing) {
- mLeftFlyoutTriangle.getOutline(triangleOutline);
- } else {
- mRightFlyoutTriangle.getOutline(triangleOutline);
- }
-
- // Offset it to the correct position, since it has no intrinsic position since
- // that is maintained by the parent LayerDrawable.
- triangleOutline.offset(
- leftPointing ? -mPointerSize : mFlyout.getWidth(),
- mFlyout.getHeight() / 2 - mPointerSize / 2);
-
- // Merge the outlines.
- final Outline compoundOutline = new Outline();
- flyoutBackground.getOutline(compoundOutline);
- compoundOutline.mPath.addPath(triangleOutline.mPath);
- outline.set(compoundOutline);
- }
- });
-
- mFlyoutText = mFlyout.findViewById(R.id.bubble_flyout_text);
- mFlyoutSpring = new SpringAnimation(mFlyoutContainer, DynamicAnimation.TRANSLATION_X);
- }
-
private void applyCurrentState() {
if (DEBUG) {
Log.d(TAG, "applyCurrentState: mIsExpanded=" + mIsExpanded);
}
+
mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
if (mIsExpanded) {
// First update the view so that it calculates a new height (ensuring the y position
@@ -1103,10 +1391,15 @@
}
}
+ mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide();
+ updateBubbleShadowsAndDotPosition(false);
+ }
+
+ /** Sets the appropriate Z-order and dot position for each bubble in the stack. */
+ private void updateBubbleShadowsAndDotPosition(boolean animate) {
int bubbsCount = mBubbleContainer.getChildCount();
for (int i = 0; i < bubbsCount; i++) {
BubbleView bv = (BubbleView) mBubbleContainer.getChildAt(i);
- bv.updateDotVisibility();
bv.setZ((BubbleController.MAX_BUBBLES
* getResources().getDimensionPixelSize(R.dimen.bubble_elevation)) - i);
@@ -1120,6 +1413,11 @@
}
});
bv.setClipToOutline(false);
+
+ // If the dot is on the left, and so is the stack, we need to change the dot position.
+ if (bv.getDotPositionOnLeft() == mStackOnLeftOrWillBe) {
+ bv.setDotPosition(!mStackOnLeftOrWillBe, animate);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
index 82e6279..8fe8bd3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
@@ -16,8 +16,6 @@
package com.android.systemui.bubbles;
-import static com.android.systemui.pip.phone.PipDismissViewController.SHOW_TARGET_DELAY;
-
import android.content.Context;
import android.graphics.PointF;
import android.os.Handler;
@@ -27,17 +25,35 @@
import android.view.ViewConfiguration;
import com.android.systemui.Dependency;
-import com.android.systemui.pip.phone.PipDismissViewController;
/**
* Handles interpreting touches on a {@link BubbleStackView}. This includes expanding, collapsing,
* dismissing, and flings.
*/
class BubbleTouchHandler implements View.OnTouchListener {
- /** Velocity required to dismiss a bubble without dragging it into the dismiss target. */
- private static final float DISMISS_MIN_VELOCITY = 4000f;
+ /** Velocity required to dismiss the stack without dragging it into the dismiss target. */
+ private static final float STACK_DISMISS_MIN_VELOCITY = 4000f;
+
+ /**
+ * Velocity required to dismiss an individual bubble without dragging it into the dismiss
+ * target.
+ *
+ * This is higher than the stack dismiss velocity since unlike the stack, a downward fling could
+ * also be an attempted gesture to return the bubble to the row of expanded bubbles, which would
+ * usually be below the dragged bubble. By increasing the required velocity, it's less likely
+ * that the user is trying to drop it back into the row vs. fling it away.
+ */
+ private static final float INDIVIDUAL_BUBBLE_DISMISS_MIN_VELOCITY = 6000f;
private static final String TAG = "BubbleTouchHandler";
+ /**
+ * When the stack is flung towards the bottom of the screen, it'll be dismissed if it's flung
+ * towards the center of the screen (where the dismiss target is). This value is the width of
+ * the target area to be considered 'towards the target'. For example 50% means that the stack
+ * needs to be flung towards the middle 50%, and the 25% on the left and right sides won't
+ * count.
+ */
+ private static final float DISMISS_FLING_TARGET_WIDTH_PERCENT = 0.5f;
private final PointF mTouchDown = new PointF();
private final PointF mViewPositionOnTouchDown = new PointF();
@@ -45,7 +61,6 @@
private final BubbleData mBubbleData;
private BubbleController mController = Dependency.get(BubbleController.class);
- private PipDismissViewController mDismissViewController;
private boolean mMovedEnough;
private int mTouchSlopSquared;
@@ -53,12 +68,6 @@
private boolean mInDismissTarget;
private Handler mHandler = new Handler();
- private Runnable mShowDismissAffordance = new Runnable() {
- @Override
- public void run() {
- mDismissViewController.showDismissTarget();
- }
- };
/** View that was initially touched, when we received the first ACTION_DOWN event. */
private View mTouchedView;
@@ -67,7 +76,6 @@
BubbleData bubbleData, Context context) {
final int touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mTouchSlopSquared = touchSlop * touchSlop;
- mDismissViewController = new PipDismissViewController(context);
mBubbleData = bubbleData;
mStack = stackView;
}
@@ -103,17 +111,13 @@
trackMovement(event);
mTouchDown.set(rawX, rawY);
-
- if (!isFlyout) {
- mDismissViewController.createDismissTarget();
- mHandler.postDelayed(mShowDismissAffordance, SHOW_TARGET_DELAY);
- }
+ mStack.onGestureStart();
if (isStack) {
mViewPositionOnTouchDown.set(mStack.getStackPosition());
mStack.onDragStart();
} else if (isFlyout) {
- // TODO(b/129768381): Make the flyout dismissable with a gesture.
+ mStack.onFlyoutDragStart();
} else {
mViewPositionOnTouchDown.set(
mTouchedView.getTranslationX(), mTouchedView.getTranslationY());
@@ -134,15 +138,26 @@
if (isStack) {
mStack.onDragged(viewX, viewY);
} else if (isFlyout) {
- // TODO(b/129768381): Make the flyout dismissable with a gesture.
+ mStack.onFlyoutDragged(deltaX);
} else {
mStack.onBubbleDragged(mTouchedView, viewX, viewY);
}
}
- // TODO - when we're in the target stick to it / animate in some way?
- mInDismissTarget = mDismissViewController.updateTarget(
- isStack ? mStack.getBubbleAt(0) : mTouchedView);
+ final boolean currentlyInDismissTarget = mStack.isInDismissTarget(event);
+ if (currentlyInDismissTarget != mInDismissTarget) {
+ mInDismissTarget = currentlyInDismissTarget;
+
+ mVelocityTracker.computeCurrentVelocity(/* maxVelocity */ 1000);
+ final float velX = mVelocityTracker.getXVelocity();
+ final float velY = mVelocityTracker.getYVelocity();
+
+ // If the touch event is within the dismiss target, magnet the stack to it.
+ if (!isFlyout) {
+ mStack.animateMagnetToDismissTarget(
+ mTouchedView, mInDismissTarget, viewX, viewY, velX, velY);
+ }
+ }
break;
case MotionEvent.ACTION_CANCEL:
@@ -151,32 +166,46 @@
case MotionEvent.ACTION_UP:
trackMovement(event);
- if (mInDismissTarget && isStack) {
- mController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
- mStack.onDragFinishAsDismiss();
+ mVelocityTracker.computeCurrentVelocity(/* maxVelocity */ 1000);
+ final float velX = mVelocityTracker.getXVelocity();
+ final float velY = mVelocityTracker.getYVelocity();
+
+ final boolean shouldDismiss =
+ isStack
+ ? mInDismissTarget
+ || isFastFlingTowardsDismissTarget(rawX, rawY, velX, velY)
+ : mInDismissTarget
+ || velY > INDIVIDUAL_BUBBLE_DISMISS_MIN_VELOCITY;
+
+ if (isFlyout && mMovedEnough) {
+ mStack.onFlyoutDragFinished(rawX - mTouchDown.x /* deltaX */, velX);
+ } else if (shouldDismiss) {
+ final String individualBubbleKey =
+ isStack ? null : ((BubbleView) mTouchedView).getKey();
+ mStack.magnetToStackIfNeededThenAnimateDismissal(mTouchedView, velX, velY,
+ () -> {
+ if (isStack) {
+ mController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
+ } else {
+ mController.removeBubble(
+ individualBubbleKey,
+ BubbleController.DISMISS_USER_GESTURE);
+ }
+ });
} else if (isFlyout) {
// TODO(b/129768381): Expand if tapped, dismiss if swiped away.
if (!mBubbleData.isExpanded() && !mMovedEnough) {
mBubbleData.setExpanded(true);
}
} else if (mMovedEnough) {
- mVelocityTracker.computeCurrentVelocity(/* maxVelocity */ 1000);
- final float velX = mVelocityTracker.getXVelocity();
- final float velY = mVelocityTracker.getYVelocity();
if (isStack) {
mStack.onDragFinish(viewX, viewY, velX, velY);
} else {
- final boolean dismissed = mInDismissTarget || velY > DISMISS_MIN_VELOCITY;
- mStack.onBubbleDragFinish(
- mTouchedView, viewX, viewY, velX, velY, /* dismissed */ dismissed);
- if (dismissed) {
- mController.removeBubble(((BubbleView) mTouchedView).getKey(),
- BubbleController.DISMISS_USER_GESTURE);
- }
+ mStack.onBubbleDragFinish(mTouchedView, viewX, viewY, velX, velY);
}
} else if (mTouchedView == mStack.getExpandedBubbleView()) {
mBubbleData.setExpanded(false);
- } else if (isStack) {
+ } else if (isStack || isFlyout) {
// Toggle expansion
mBubbleData.setExpanded(!mBubbleData.isExpanded());
} else {
@@ -191,27 +220,50 @@
return true;
}
+ /**
+ * Whether the given touch data represents a powerful fling towards the bottom-center of the
+ * screen (the dismiss target).
+ */
+ private boolean isFastFlingTowardsDismissTarget(
+ float rawX, float rawY, float velX, float velY) {
+ // Not a fling downward towards the target if velocity is zero or negative.
+ if (velY <= 0) {
+ return false;
+ }
+
+ float bottomOfScreenInterceptX = rawX;
+
+ // Only do math if the X velocity is non-zero, otherwise X won't change.
+ if (velX != 0) {
+ // Rise over run...
+ final float slope = velY / velX;
+ // ...y = mx + b, b = y / mx...
+ final float yIntercept = rawY - slope * rawX;
+ // ...calculate the x value when y = bottom of the screen.
+ bottomOfScreenInterceptX = (mStack.getHeight() - yIntercept) / slope;
+ }
+
+ final float dismissTargetWidth =
+ mStack.getWidth() * DISMISS_FLING_TARGET_WIDTH_PERCENT;
+ return velY > STACK_DISMISS_MIN_VELOCITY
+ && bottomOfScreenInterceptX > dismissTargetWidth / 2f
+ && bottomOfScreenInterceptX < mStack.getWidth() - dismissTargetWidth / 2f;
+ }
+
/** Clears all touch-related state. */
private void resetForNextGesture() {
- cleanUpDismissTarget();
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
+
mTouchedView = null;
mMovedEnough = false;
mInDismissTarget = false;
- }
- /**
- * Removes the dismiss target and cancels any pending callbacks to show it.
- */
- private void cleanUpDismissTarget() {
- mHandler.removeCallbacks(mShowDismissAffordance);
- mDismissViewController.destroyDismissTarget();
+ mStack.onGestureFinished();
}
-
private void trackMovement(MotionEvent event) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index 2681b6d..aa32b94 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -48,9 +48,12 @@
private Context mContext;
private BadgedImageView mBadgedImageView;
+ private int mBadgeColor;
private int mPadding;
private int mIconInset;
+ private boolean mSuppressDot = false;
+
private NotificationEntry mEntry;
public BubbleView(Context context) {
@@ -130,18 +133,54 @@
return (mEntry != null) ? mEntry.getRow() : null;
}
+ /** Changes the dot's visibility to match the bubble view's state. */
+ void updateDotVisibility(boolean animate) {
+ updateDotVisibility(animate, null /* after */);
+ }
+
/**
- * Marks this bubble as "read", i.e. no badge should show.
+ * Changes the dot's visibility to match the bubble view's state, running the provided callback
+ * after animation if requested.
*/
- public void updateDotVisibility() {
- boolean showDot = getEntry().showInShadeWhenBubble();
- animateDot(showDot);
+ void updateDotVisibility(boolean animate, Runnable after) {
+ boolean showDot = getEntry().showInShadeWhenBubble() && !mSuppressDot;
+
+ if (animate) {
+ animateDot(showDot, after);
+ } else {
+ mBadgedImageView.setShowDot(showDot);
+ }
+ }
+
+ /**
+ * Sets whether or not to hide the dot even if we'd otherwise show it. This is used while the
+ * flyout is visible or animating, to hide the dot until the flyout visually transforms into it.
+ */
+ void setSuppressDot(boolean suppressDot, boolean animate) {
+ mSuppressDot = suppressDot;
+ updateDotVisibility(animate);
+ }
+
+ /** Sets the position of the 'new' dot, animating it out and back in if requested. */
+ void setDotPosition(boolean onLeft, boolean animate) {
+ if (animate && onLeft != mBadgedImageView.getDotPosition() && !mSuppressDot) {
+ animateDot(false /* showDot */, () -> {
+ mBadgedImageView.setDotPosition(onLeft);
+ animateDot(true /* showDot */, null);
+ });
+ } else {
+ mBadgedImageView.setDotPosition(onLeft);
+ }
+ }
+
+ boolean getDotPositionOnLeft() {
+ return mBadgedImageView.getDotPosition();
}
/**
* Animates the badge to show or hide.
*/
- private void animateDot(boolean showDot) {
+ private void animateDot(boolean showDot, Runnable after) {
if (mBadgedImageView.isShowingDot() != showDot) {
mBadgedImageView.setShowDot(showDot);
mBadgedImageView.clearAnimation();
@@ -152,9 +191,13 @@
fraction = showDot ? fraction : 1 - fraction;
mBadgedImageView.setDotScale(fraction);
}).withEndAction(() -> {
- if (!showDot) {
- mBadgedImageView.setShowDot(false);
- }
+ if (!showDot) {
+ mBadgedImageView.setShowDot(false);
+ }
+
+ if (after != null) {
+ after.run();
+ }
}).start();
}
}
@@ -181,8 +224,13 @@
mBadgedImageView.setImageDrawable(iconDrawable);
}
int badgeColor = determineDominateColor(iconDrawable, n.color);
+ mBadgeColor = badgeColor;
mBadgedImageView.setDotColor(badgeColor);
- animateDot(mEntry.showInShadeWhenBubble() /* showDot */);
+ animateDot(mEntry.showInShadeWhenBubble() /* showDot */, null /* after */);
+ }
+
+ int getBadgeColor() {
+ return mBadgeColor;
}
private Drawable buildIconWithTint(Drawable iconDrawable, int backgroundColor) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 95fbfe3..a9ad464 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -64,6 +64,20 @@
/** Size of dismiss target at bottom of screen. */
private float mPipDismissHeight;
+ /** Whether the dragged-out bubble is in the dismiss target. */
+ private boolean mIndividualBubbleWithinDismissTarget = false;
+
+ /**
+ * Whether the dragged out bubble is springing towards the touch point, rather than using the
+ * default behavior of moving directly to the touch point.
+ *
+ * This happens when the user's finger exits the dismiss area while the bubble is magnetized to
+ * the center. Since the touch point differs from the bubble location, we need to animate the
+ * bubble back to the touch point to avoid a jarring instant location change from the center of
+ * the target to the touch point just outside the target bounds.
+ */
+ private boolean mSpringingBubbleToTouch = false;
+
public ExpandedAnimationController(Point displaySize) {
mDisplaySize = displaySize;
}
@@ -151,8 +165,23 @@
* bubble is dragged back into the row.
*/
public void dragBubbleOut(View bubbleView, float x, float y) {
- bubbleView.setTranslationX(x);
- bubbleView.setTranslationY(y);
+ if (mSpringingBubbleToTouch) {
+ if (mLayout.arePropertiesAnimatingOnView(
+ bubbleView, DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y)) {
+ animationForChild(mBubbleDraggingOut)
+ .translationX(x)
+ .translationY(y)
+ .withStiffness(SpringForce.STIFFNESS_HIGH)
+ .start();
+ } else {
+ mSpringingBubbleToTouch = false;
+ }
+ }
+
+ if (!mSpringingBubbleToTouch && !mIndividualBubbleWithinDismissTarget) {
+ bubbleView.setTranslationX(x);
+ bubbleView.setTranslationY(y);
+ }
final boolean draggedOutEnough =
y > getExpandedY() + mBubbleSizePx || y < getExpandedY() - mBubbleSizePx;
@@ -164,6 +193,53 @@
}
}
+ /** Plays a dismiss animation on the dragged out bubble. */
+ public void dismissDraggedOutBubble(Runnable after) {
+ mIndividualBubbleWithinDismissTarget = false;
+
+ // Fill the space from the soon to be dismissed bubble.
+ animateStackByBubbleWidthsStartingFrom(
+ /* numBubbleWidths */ -1,
+ /* startIndex */ mLayout.indexOfChild(mBubbleDraggingOut) + 1);
+
+ animationForChild(mBubbleDraggingOut)
+ .withStiffness(SpringForce.STIFFNESS_HIGH)
+ .scaleX(1.1f)
+ .scaleY(1.1f)
+ .alpha(0f, after)
+ .start();
+ }
+
+ /** Magnets the given bubble to the dismiss target. */
+ public void magnetBubbleToDismiss(
+ View bubbleView, float velX, float velY, float destY, Runnable after) {
+ mIndividualBubbleWithinDismissTarget = true;
+ mSpringingBubbleToTouch = false;
+ animationForChild(bubbleView)
+ .withStiffness(SpringForce.STIFFNESS_MEDIUM)
+ .withDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
+ .withPositionStartVelocities(velX, velY)
+ .translationX(mLayout.getWidth() / 2f - mBubbleSizePx / 2f)
+ .translationY(destY, after)
+ .start();
+ }
+
+ /**
+ * Springs the dragged-out bubble towards the given coordinates and sets flags to have touch
+ * events update the spring's final position until it's settled.
+ */
+ public void demagnetizeBubbleTo(float x, float y, float velX, float velY) {
+ mIndividualBubbleWithinDismissTarget = false;
+ mSpringingBubbleToTouch = true;
+
+ animationForChild(mBubbleDraggingOut)
+ .translationX(x)
+ .translationY(y)
+ .withPositionStartVelocities(velX, velY)
+ .withStiffness(SpringForce.STIFFNESS_HIGH)
+ .start();
+ }
+
/**
* Snaps a bubble back to its position within the bubble row, and animates the rest of the
* bubbles to accommodate it if it was previously dragged out past the threshold.
@@ -274,28 +350,21 @@
@Override
void onChildRemoved(View child, int index, Runnable finishRemoval) {
- // Bubble pops out to the top.
- // TODO: Reverse this when bubbles are at the bottom.
-
final PhysicsAnimationLayout.PhysicsPropertyAnimator animator = animationForChild(child);
- animator.alpha(0f, finishRemoval /* endAction */);
// If we're removing the dragged-out bubble, that means it got dismissed.
if (child.equals(mBubbleDraggingOut)) {
- animator.position(
- mLayout.getWidth() / 2f - mBubbleSizePx / 2f,
- mLayout.getHeight() + mBubbleSizePx)
- .withPositionStartVelocities(mBubbleDraggingOutVelX, mBubbleDraggingOutVelY)
- .scaleX(ANIMATE_SCALE_PERCENT)
- .scaleY(ANIMATE_SCALE_PERCENT);
-
mBubbleDraggingOut = null;
+ finishRemoval.run();
} else {
- animator.translationY(getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR);
+ animator.alpha(0f, finishRemoval /* endAction */)
+ .withStiffness(SpringForce.STIFFNESS_HIGH)
+ .withDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY)
+ .scaleX(1.1f)
+ .scaleY(1.1f)
+ .start();
}
- animator.start();
-
// Animate all the other bubbles to their new positions sans this bubble.
animateBubblesAfterIndexToCorrectX(index);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
index 4606526..997d2c4 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
@@ -290,6 +290,10 @@
final Runnable checkIfAllFinished = () -> {
if (!arePropertiesAnimating(properties)) {
action.run();
+
+ for (DynamicAnimation.ViewProperty property : properties) {
+ removeEndActionForProperty(property);
+ }
}
};
@@ -379,10 +383,21 @@
/** Checks whether any animations of the given properties are still running. */
public boolean arePropertiesAnimating(DynamicAnimation.ViewProperty... properties) {
for (int i = 0; i < getChildCount(); i++) {
- for (DynamicAnimation.ViewProperty property : properties) {
- if (getAnimationAtIndex(property, i).isRunning()) {
- return true;
- }
+ if (arePropertiesAnimatingOnView(getChildAt(i), properties)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /** Checks whether any animations of the given properties are running on the given view. */
+ public boolean arePropertiesAnimatingOnView(
+ View view, DynamicAnimation.ViewProperty... properties) {
+ for (DynamicAnimation.ViewProperty property : properties) {
+ final SpringAnimation animation = getAnimationFromView(property, view);
+ if (animation != null && animation.isRunning()) {
+ return true;
}
}
@@ -556,7 +571,11 @@
DynamicAnimation anim, boolean canceled, float value, float velocity) {
if (!arePropertiesAnimating(mProperty)) {
if (mEndActionForProperty.containsKey(mProperty)) {
- mEndActionForProperty.get(mProperty).run();
+ final Runnable callback = mEndActionForProperty.get(mProperty);
+
+ if (callback != null) {
+ callback.run();
+ }
}
}
}
@@ -578,6 +597,12 @@
/** Start delay to use when start is called. */
private long mStartDelay = 0;
+ /** Damping ratio to use for the animations. */
+ private float mDampingRatio = -1;
+
+ /** Stiffness to use for the animations. */
+ private float mStiffness = -1;
+
/** End actions to call when animations for the given property complete. */
private Map<DynamicAnimation.ViewProperty, Runnable[]> mEndActionsForProperty =
new HashMap<>();
@@ -687,6 +712,24 @@
}
/**
+ * Set the damping ratio to use for this animation. If not supplied, will default to the
+ * value from {@link PhysicsAnimationController#getSpringForce}.
+ */
+ public PhysicsPropertyAnimator withDampingRatio(float dampingRatio) {
+ mDampingRatio = dampingRatio;
+ return this;
+ }
+
+ /**
+ * Set the stiffness to use for this animation. If not supplied, will default to the
+ * value from {@link PhysicsAnimationController#getSpringForce}.
+ */
+ public PhysicsPropertyAnimator withStiffness(float stiffness) {
+ mStiffness = stiffness;
+ return this;
+ }
+
+ /**
* Set the start velocities to use for TRANSLATION_X and TRANSLATION_Y animations. This
* overrides any value set via {@link #withStartVelocity(float)} for those properties.
*/
@@ -711,12 +754,14 @@
// If there are end actions, set an end listener on the layout for all the properties
// we're about to animate.
- if (after != null) {
+ if (after != null && after.length > 0) {
final DynamicAnimation.ViewProperty[] propertiesArray =
properties.toArray(new DynamicAnimation.ViewProperty[0]);
- for (Runnable callback : after) {
- setEndActionForMultipleProperties(callback, propertiesArray);
- }
+ setEndActionForMultipleProperties(() -> {
+ for (Runnable callback : after) {
+ callback.run();
+ }
+ }, propertiesArray);
}
// If we used position-specific end actions, we'll need to listen for both TRANSLATION_X
@@ -746,12 +791,15 @@
// Actually start the animations.
for (DynamicAnimation.ViewProperty property : properties) {
+ final SpringForce defaultSpringForce = mController.getSpringForce(property, mView);
animateValueForChild(
property,
mView,
mAnimatedProperties.get(property),
mPositionStartVelocities.getOrDefault(property, mDefaultStartVelocity),
mStartDelay,
+ mStiffness >= 0 ? mStiffness : defaultSpringForce.getStiffness(),
+ mDampingRatio >= 0 ? mDampingRatio : defaultSpringForce.getDampingRatio(),
mEndActionsForProperty.get(property));
}
@@ -760,6 +808,8 @@
mPositionStartVelocities.clear();
mDefaultStartVelocity = 0;
mStartDelay = 0;
+ mStiffness = -1;
+ mDampingRatio = -1;
mEndActionsForProperty.clear();
}
@@ -778,6 +828,8 @@
float value,
float startVel,
long startDelay,
+ float stiffness,
+ float dampingRatio,
Runnable[] afterCallbacks) {
if (view != null) {
final SpringAnimation animation =
@@ -795,6 +847,9 @@
});
}
+ animation.getSpring().setStiffness(stiffness);
+ animation.getSpring().setDampingRatio(dampingRatio);
+
if (startVel > 0) {
animation.setStartVelocity(startVel);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index 47f2cd4..8529ed4 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -30,7 +30,6 @@
import androidx.dynamicanimation.animation.SpringForce;
import com.android.systemui.R;
-import com.android.systemui.bubbles.BubbleController;
import com.google.android.collect.Sets;
@@ -116,6 +115,25 @@
*/
private boolean mIsMovingFromFlinging = false;
+ /**
+ * Whether the stack is within the dismiss target (either by being dragged, magnet'd, or flung).
+ */
+ private boolean mWithinDismissTarget = false;
+
+ /**
+ * Whether the first bubble is springing towards the touch point, rather than using the default
+ * behavior of moving directly to the touch point with the rest of the stack following it.
+ *
+ * This happens when the user's finger exits the dismiss area while the stack is magnetized to
+ * the center. Since the touch point differs from the stack location, we need to animate the
+ * stack back to the touch point to avoid a jarring instant location change from the center of
+ * the target to the touch point just outside the target bounds.
+ *
+ * This is reset once the spring animations end, since that means the first bubble has
+ * successfully 'caught up' to the touch.
+ */
+ private boolean mFirstBubbleSpringingToTouch = false;
+
/** Horizontal offset of bubbles in the stack. */
private float mStackOffset;
/** Diameter of the bubbles themselves. */
@@ -175,18 +193,42 @@
/** Whether the stack is on the left side of the screen. */
public boolean isStackOnLeftSide() {
- if (mLayout != null) {
- return mStackPosition.x - mIndividualBubbleSize / 2 < mLayout.getWidth() / 2;
- } else {
+ if (mLayout == null) {
return false;
}
+ float stackCenter = mStackPosition.x + mIndividualBubbleSize / 2;
+ float screenCenter = mLayout.getWidth() / 2;
+ return stackCenter < screenCenter;
+ }
+
+ /**
+ * Fling stack to given corner, within allowable screen bounds.
+ * Note that we need new SpringForce instances per animation despite identical configs because
+ * SpringAnimation uses SpringForce's internal (changing) velocity while the animation runs.
+ */
+ public void springStack(float destinationX, float destinationY) {
+ springFirstBubbleWithStackFollowing(DynamicAnimation.TRANSLATION_X,
+ new SpringForce()
+ .setStiffness(SPRING_AFTER_FLING_STIFFNESS)
+ .setDampingRatio(SPRING_AFTER_FLING_DAMPING_RATIO),
+ 0 /* startXVelocity */,
+ destinationX);
+
+ springFirstBubbleWithStackFollowing(DynamicAnimation.TRANSLATION_Y,
+ new SpringForce()
+ .setStiffness(SPRING_AFTER_FLING_STIFFNESS)
+ .setDampingRatio(SPRING_AFTER_FLING_DAMPING_RATIO),
+ 0 /* startYVelocity */,
+ destinationY);
}
/**
* Flings the stack starting with the given velocities, springing it to the nearest edge
* afterward.
+ *
+ * @return The X value that the stack will end up at after the fling/spring.
*/
- public void flingStackThenSpringToEdge(float x, float velX, float velY) {
+ public float flingStackThenSpringToEdge(float x, float velX, float velY) {
final boolean stackOnLeftSide = x - mIndividualBubbleSize / 2 < mLayout.getWidth() / 2;
final boolean stackShouldFlingLeft = stackOnLeftSide
@@ -241,6 +283,7 @@
DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
mIsMovingFromFlinging = true;
+ return destinationRelativeX;
}
/**
@@ -352,6 +395,7 @@
float destinationY = Float.MIN_VALUE;
if (imeVisible) {
+ // Stack is lower than it should be and overlaps the now-visible IME.
if (mStackPosition.y > maxBubbleY && mPreImeY == Float.MIN_VALUE) {
mPreImeY = mStackPosition.y;
destinationY = maxBubbleY;
@@ -422,6 +466,120 @@
return allowableRegion;
}
+ /** Moves the stack in response to a touch event. */
+ public void moveStackFromTouch(float x, float y) {
+
+ // If we're springing to the touch point to 'catch up' after dragging out of the dismiss
+ // target, then update the stack position animations instead of moving the bubble directly.
+ if (mFirstBubbleSpringingToTouch) {
+ final SpringAnimation springToTouchX =
+ (SpringAnimation) mStackPositionAnimations.get(DynamicAnimation.TRANSLATION_X);
+ final SpringAnimation springToTouchY =
+ (SpringAnimation) mStackPositionAnimations.get(DynamicAnimation.TRANSLATION_Y);
+
+ // If either animation is still running, we haven't caught up. Update the animations.
+ if (springToTouchX.isRunning() || springToTouchY.isRunning()) {
+ springToTouchX.animateToFinalPosition(x);
+ springToTouchY.animateToFinalPosition(y);
+ } else {
+ // If the animations have finished, the stack is now at the touch point. We can
+ // resume moving the bubble directly.
+ mFirstBubbleSpringingToTouch = false;
+ }
+ }
+
+ if (!mFirstBubbleSpringingToTouch && !mWithinDismissTarget) {
+ moveFirstBubbleWithStackFollowing(x, y);
+ }
+ }
+
+ /**
+ * Demagnetizes the stack, springing it towards the given point. This also sets flags so that
+ * subsequent touch events will update the final position of the demagnetization spring instead
+ * of directly moving the bubbles, until demagnetization is complete.
+ */
+ public void demagnetizeFromDismissToPoint(float x, float y, float velX, float velY) {
+ mWithinDismissTarget = false;
+ mFirstBubbleSpringingToTouch = true;
+
+ springFirstBubbleWithStackFollowing(
+ DynamicAnimation.TRANSLATION_X,
+ new SpringForce()
+ .setDampingRatio(DEFAULT_BOUNCINESS)
+ .setStiffness(DEFAULT_STIFFNESS),
+ velX, x);
+
+ springFirstBubbleWithStackFollowing(
+ DynamicAnimation.TRANSLATION_Y,
+ new SpringForce()
+ .setDampingRatio(DEFAULT_BOUNCINESS)
+ .setStiffness(DEFAULT_STIFFNESS),
+ velY, y);
+ }
+
+ /**
+ * Spring the stack towards the dismiss target, respecting existing velocity. This also sets
+ * flags so that subsequent touch events will not move the stack until it's demagnetized.
+ */
+ public void magnetToDismiss(float velX, float velY, float destY, Runnable after) {
+ mWithinDismissTarget = true;
+ mFirstBubbleSpringingToTouch = false;
+
+ animationForChildAtIndex(0)
+ .translationX(mLayout.getWidth() / 2f - mIndividualBubbleSize / 2f)
+ .translationY(destY, after)
+ .withPositionStartVelocities(velX, velY)
+ .withStiffness(SpringForce.STIFFNESS_MEDIUM)
+ .withDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
+ .start();
+ }
+
+ /**
+ * 'Implode' the stack by shrinking the bubbles via chained animations and fading them out.
+ */
+ public void implodeStack(Runnable after) {
+ // Pop and fade the bubbles sequentially.
+ animationForChildAtIndex(0)
+ .scaleX(0.5f)
+ .scaleY(0.5f)
+ .alpha(0f)
+ .withDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY)
+ .withStiffness(SpringForce.STIFFNESS_HIGH)
+ .start(() -> {
+ // Run the callback and reset flags. The child translation animations might
+ // still be running, but that's fine. Once the alpha is at 0f they're no longer
+ // visible anyway.
+ after.run();
+ mWithinDismissTarget = false;
+ });
+ }
+
+ /**
+ * Springs the first bubble to the given final position, with the rest of the stack 'following'.
+ */
+ protected void springFirstBubbleWithStackFollowing(
+ DynamicAnimation.ViewProperty property, SpringForce spring,
+ float vel, float finalPosition) {
+
+ if (mLayout.getChildCount() == 0) {
+ return;
+ }
+
+ Log.d(TAG, String.format("Springing %s to final position %f.",
+ PhysicsAnimationLayout.getReadablePropertyName(property),
+ finalPosition));
+
+ StackPositionProperty firstBubbleProperty = new StackPositionProperty(property);
+ SpringAnimation springAnimation =
+ new SpringAnimation(this, firstBubbleProperty)
+ .setSpring(spring)
+ .setStartVelocity(vel);
+
+ cancelStackPositionAnimation(property);
+ mStackPositionAnimations.put(property, springAnimation);
+ springAnimation.animateToFinalPosition(finalPosition);
+ }
+
@Override
Set<DynamicAnimation.ViewProperty> getAnimatedProperties() {
return Sets.newHashSet(
@@ -436,7 +594,9 @@
int getNextAnimationInChain(DynamicAnimation.ViewProperty property, int index) {
if (property.equals(DynamicAnimation.TRANSLATION_X)
|| property.equals(DynamicAnimation.TRANSLATION_Y)) {
- return index + 1; // Just chain them linearly.
+ return index + 1;
+ } else if (mWithinDismissTarget) {
+ return index + 1; // Chain all animations in dismiss (scale, alpha, etc. are used).
} else {
return NONE;
}
@@ -446,9 +606,15 @@
@Override
float getOffsetForChainedPropertyAnimation(DynamicAnimation.ViewProperty property) {
if (property.equals(DynamicAnimation.TRANSLATION_X)) {
- // Offset to the left if we're on the left, or the right otherwise.
- return mLayout.isFirstChildXLeftOfCenter(mStackPosition.x)
- ? -mStackOffset : mStackOffset;
+ // If we're in the dismiss target, have the bubbles pile on top of each other with no
+ // offset.
+ if (mWithinDismissTarget) {
+ return 0f;
+ } else {
+ // Offset to the left if we're on the left, or the right otherwise.
+ return mLayout.isFirstChildXLeftOfCenter(mStackPosition.x)
+ ? -mStackOffset : mStackOffset;
+ }
} else {
return 0f;
}
@@ -457,11 +623,8 @@
@Override
SpringForce getSpringForce(DynamicAnimation.ViewProperty property, View view) {
return new SpringForce()
- .setDampingRatio(BubbleController.getBubbleBounciness(
- mLayout.getContext(), DEFAULT_BOUNCINESS))
- .setStiffness(BubbleController.getBubbleStiffness(
- mLayout.getContext(),
- mIsMovingFromFlinging ? FLING_FOLLOW_STIFFNESS : DEFAULT_STIFFNESS));
+ .setDampingRatio(DEFAULT_BOUNCINESS)
+ .setStiffness(mIsMovingFromFlinging ? FLING_FOLLOW_STIFFNESS : DEFAULT_STIFFNESS);
}
@Override
@@ -571,32 +734,6 @@
}
/**
- * Springs the first bubble to the given final position, with the rest of the stack 'following'.
- */
- private void springFirstBubbleWithStackFollowing(
- DynamicAnimation.ViewProperty property, SpringForce spring,
- float vel, float finalPosition) {
-
- if (mLayout.getChildCount() == 0) {
- return;
- }
-
- Log.d(TAG, String.format("Springing %s to final position %f.",
- PhysicsAnimationLayout.getReadablePropertyName(property),
- finalPosition));
-
- StackPositionProperty firstBubbleProperty = new StackPositionProperty(property);
- SpringAnimation springAnimation =
- new SpringAnimation(this, firstBubbleProperty)
- .setSpring(spring)
- .setStartVelocity(vel);
-
- cancelStackPositionAnimation(property);
- mStackPositionAnimations.put(property, springAnimation);
- springAnimation.animateToFinalPosition(finalPosition);
- }
-
- /**
* Cancels any outstanding first bubble property animations that are running. This does not
* affect the SpringAnimations controlling the individual bubbles' 'following' effect - it only
* cancels animations started from {@link #springFirstBubbleWithStackFollowing} and
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java b/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
index c83c74f..587abba 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
@@ -26,6 +26,9 @@
* example, provide information on the current touch state.
*/
public class ClassifierData {
+ private static final long MINIMUM_DT_NANOS = 16666666; // 60Hz
+ private static final long MINIMUM_DT_SMEAR_NANOS = 2500000; // 2.5ms
+
private SparseArray<Stroke> mCurrentStrokes = new SparseArray<>();
private ArrayList<Stroke> mEndingStrokes = new ArrayList<>();
private final float mDpi;
@@ -34,7 +37,18 @@
mDpi = dpi;
}
- public void update(MotionEvent event) {
+ /** Returns true if the event should be considered, false otherwise. */
+ public boolean update(MotionEvent event) {
+ // We limit to 60hz sampling. Drop anything happening faster than that.
+ // Legacy code was created with an assumed sampling rate. As devices increase their
+ // sampling rate, this creates potentialy false positives.
+ if (event.getActionMasked() == MotionEvent.ACTION_MOVE
+ && mCurrentStrokes.size() != 0
+ && event.getEventTimeNano() - mCurrentStrokes.valueAt(0).getLastEventTimeNano()
+ < MINIMUM_DT_NANOS - MINIMUM_DT_SMEAR_NANOS) {
+ return false;
+ }
+
mEndingStrokes.clear();
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
@@ -54,6 +68,8 @@
mEndingStrokes.add(getStroke(id));
}
}
+
+ return true;
}
public void cleanUp(MotionEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFactory.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFactory.java
new file mode 100644
index 0000000..01921f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open 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.classifier;
+
+import android.content.Context;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.FalsingManager;
+
+/**
+ * When the phone is locked, listens to touch, sensor and phone events and sends them to
+ * DataCollector and HumanInteractionClassifier.
+ *
+ * It does not collect touch events when the bouncer shows up.
+ *
+ * TODO: FalsingManager supports dependency injection. Use it.
+ */
+public class FalsingManagerFactory {
+ private static FalsingManager sInstance = null;
+
+ private FalsingManagerFactory() {}
+
+ public static FalsingManager getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = Dependency.get(FalsingManager.class);
+ }
+ return sInstance;
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
similarity index 80%
rename from packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
rename to packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
index a63fdbd..6fb6467 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.classifier;
@@ -22,6 +22,7 @@
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.hardware.biometrics.BiometricSourceType;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
@@ -32,9 +33,13 @@
import android.view.MotionEvent;
import android.view.accessibility.AccessibilityManager;
+import com.android.internal.logging.MetricsLogger;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.analytics.DataCollector;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.StatusBarState;
@@ -48,7 +53,7 @@
*
* It does not collect touch events when the bouncer shows up.
*/
-public class FalsingManager implements SensorEventListener, StateListener {
+public class FalsingManagerImpl implements FalsingManager {
private static final String ENFORCE_BOUNCER = "falsing_manager_enforce_bouncer";
private static final int[] CLASSIFIER_SENSORS = new int[] {
@@ -62,6 +67,8 @@
Sensor.TYPE_LIGHT,
Sensor.TYPE_ROTATION_VECTOR,
};
+ private static final String FALSING_REMAIN_LOCKED = "falsing_failure_after_attempts";
+ private static final String FALSING_SUCCESS = "falsing_success_after_attempts";
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final Context mContext;
@@ -72,17 +79,45 @@
private final AccessibilityManager mAccessibilityManager;
private final UiOffloadThread mUiOffloadThread;
- private static FalsingManager sInstance = null;
-
private boolean mEnforceBouncer = false;
private boolean mBouncerOn = false;
private boolean mBouncerOffOnDown = false;
private boolean mSessionActive = false;
private boolean mIsTouchScreen = true;
+ private boolean mJustUnlockedWithFace = false;
private int mState = StatusBarState.SHADE;
private boolean mScreenOn;
private boolean mShowingAod;
private Runnable mPendingWtf;
+ private int mIsFalseTouchCalls;
+ private MetricsLogger mMetricsLogger;
+
+ private SensorEventListener mSensorEventListener = new SensorEventListener() {
+ @Override
+ public synchronized void onSensorChanged(SensorEvent event) {
+ mDataCollector.onSensorChanged(event);
+ mHumanInteractionClassifier.onSensorChanged(event);
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ mDataCollector.onAccuracyChanged(sensor, accuracy);
+ }
+ };
+
+ public StateListener mStatusBarStateListener = new StateListener() {
+ @Override
+ public void onStateChanged(int newState) {
+ if (FalsingLog.ENABLED) {
+ FalsingLog.i("setStatusBarState", new StringBuilder()
+ .append("from=").append(StatusBarState.toShortString(mState))
+ .append(" to=").append(StatusBarState.toShortString(newState))
+ .toString());
+ }
+ mState = newState;
+ updateSessionActive();
+ }
+ };
protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@Override
@@ -90,8 +125,19 @@
updateConfiguration();
}
};
+ private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onBiometricAuthenticated(int userId,
+ BiometricSourceType biometricSourceType) {
+ if (userId == KeyguardUpdateMonitor.getCurrentUser()
+ && biometricSourceType == BiometricSourceType.FACE) {
+ mJustUnlockedWithFace = true;
+ }
+ }
+ };
- private FalsingManager(Context context) {
+ FalsingManagerImpl(Context context) {
mContext = context;
mSensorManager = Dependency.get(AsyncSensorManager.class);
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
@@ -99,6 +145,7 @@
mHumanInteractionClassifier = HumanInteractionClassifier.getInstance(mContext);
mUiOffloadThread = Dependency.get(UiOffloadThread.class);
mScreenOn = context.getSystemService(PowerManager.class).isInteractive();
+ mMetricsLogger = new MetricsLogger();
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(ENFORCE_BOUNCER), false,
@@ -106,14 +153,8 @@
UserHandle.USER_ALL);
updateConfiguration();
- Dependency.get(StatusBarStateController.class).addCallback(this);
- }
-
- public static FalsingManager getInstance(Context context) {
- if (sInstance == null) {
- sInstance = new FalsingManager(context);
- }
- return sInstance;
+ Dependency.get(StatusBarStateController.class).addCallback(mStatusBarStateListener);
+ KeyguardUpdateMonitor.getInstance(context).registerCallback(mKeyguardUpdateCallback);
}
private void updateConfiguration() {
@@ -122,13 +163,14 @@
}
private boolean shouldSessionBeActive() {
- if (FalsingLog.ENABLED && FalsingLog.VERBOSE)
+ if (FalsingLog.ENABLED && FalsingLog.VERBOSE) {
FalsingLog.v("shouldBeActive", new StringBuilder()
.append("enabled=").append(isEnabled() ? 1 : 0)
.append(" mScreenOn=").append(mScreenOn ? 1 : 0)
.append(" mState=").append(StatusBarState.toShortString(mState))
.toString()
);
+ }
return isEnabled() && mScreenOn && (mState == StatusBarState.KEYGUARD) && !mShowingAod;
}
@@ -143,10 +185,18 @@
private void sessionExitpoint(boolean force) {
if (mSessionActive && (force || !shouldSessionBeActive())) {
mSessionActive = false;
+ if (mIsFalseTouchCalls != 0) {
+ if (FalsingLog.ENABLED) {
+ FalsingLog.i(
+ "isFalseTouchCalls", "Calls before failure: " + mIsFalseTouchCalls);
+ }
+ mMetricsLogger.histogram(FALSING_REMAIN_LOCKED, mIsFalseTouchCalls);
+ mIsFalseTouchCalls = 0;
+ }
// This can be expensive, and doesn't need to happen on the main thread.
mUiOffloadThread.submit(() -> {
- mSensorManager.unregisterListener(this);
+ mSensorManager.unregisterListener(mSensorEventListener);
});
}
}
@@ -166,6 +216,8 @@
}
mBouncerOn = false;
mSessionActive = true;
+ mJustUnlockedWithFace = false;
+ mIsFalseTouchCalls = 0;
if (mHumanInteractionClassifier.isEnabled()) {
registerSensors(CLASSIFIER_SENSORS);
@@ -185,7 +237,8 @@
// This can be expensive, and doesn't need to happen on the main thread.
mUiOffloadThread.submit(() -> {
- mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
+ mSensorManager.registerListener(
+ mSensorEventListener, s, SensorManager.SENSOR_DELAY_GAME);
});
}
}
@@ -250,7 +303,21 @@
// anti-falsed.
return false;
}
- return mHumanInteractionClassifier.isFalseTouch();
+ if (mJustUnlockedWithFace) {
+ // Unlocking with face is a strong user presence signal, we can assume the user
+ // is present until the next session starts.
+ return false;
+ }
+ mIsFalseTouchCalls++;
+ boolean isFalse = mHumanInteractionClassifier.isFalseTouch();
+ if (!isFalse) {
+ if (FalsingLog.ENABLED) {
+ FalsingLog.i("isFalseTouchCalls", "Calls before success: " + mIsFalseTouchCalls);
+ }
+ mMetricsLogger.histogram(FALSING_SUCCESS, mIsFalseTouchCalls);
+ mIsFalseTouchCalls = 0;
+ }
+ return isFalse;
}
private void clearPendingWtf() {
@@ -260,16 +327,6 @@
}
}
- @Override
- public synchronized void onSensorChanged(SensorEvent event) {
- mDataCollector.onSensorChanged(event);
- mHumanInteractionClassifier.onSensorChanged(event);
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- mDataCollector.onAccuracyChanged(sensor, accuracy);
- }
public boolean shouldEnforceBouncer() {
return mEnforceBouncer;
@@ -280,18 +337,6 @@
updateSessionActive();
}
- @Override
- public void onStateChanged(int newState) {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("setStatusBarState", new StringBuilder()
- .append("from=").append(StatusBarState.toShortString(mState))
- .append(" to=").append(StatusBarState.toShortString(newState))
- .toString());
- }
- mState = newState;
- updateSessionActive();
- }
-
public void onScreenTurningOn() {
if (FalsingLog.ENABLED) {
FalsingLog.i("onScreenTurningOn", new StringBuilder()
@@ -375,8 +420,8 @@
if (FalsingLog.ENABLED) {
FalsingLog.i("onTrackingStarted", "");
}
- mHumanInteractionClassifier.setType(secure ?
- Classifier.BOUNCER_UNLOCK : Classifier.UNLOCK);
+ mHumanInteractionClassifier.setType(secure
+ ? Classifier.BOUNCER_UNLOCK : Classifier.UNLOCK);
mDataCollector.onTrackingStarted();
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
new file mode 100644
index 0000000..28454b0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.classifier;
+
+import android.content.Context;
+import android.net.Uri;
+import android.view.MotionEvent;
+
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.FalsingPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.shared.plugins.PluginManager;
+
+import java.io.PrintWriter;
+
+import javax.inject.Inject;
+
+/**
+ * Simple passthrough implementation of {@link FalsingManager} allowing plugins to swap in.
+ *
+ * {@link FalsingManagerImpl} is used when a Plugin is not loaded.
+ */
+public class FalsingManagerProxy implements FalsingManager {
+
+ private FalsingManager mInternalFalsingManager;
+
+ @Inject
+ FalsingManagerProxy(Context context, PluginManager pluginManager) {
+ mInternalFalsingManager = new FalsingManagerImpl(context);
+ final PluginListener<FalsingPlugin> mPluginListener = new PluginListener<FalsingPlugin>() {
+ public void onPluginConnected(FalsingPlugin plugin, Context context) {
+ FalsingManager pluginFalsingManager = plugin.getFalsingManager(context);
+ if (pluginFalsingManager != null) {
+ mInternalFalsingManager = pluginFalsingManager;
+ }
+ }
+
+ public void onPluginDisconnected(FalsingPlugin plugin) {
+ mInternalFalsingManager = new FalsingManagerImpl(context);
+ }
+ };
+
+ pluginManager.addPluginListener(mPluginListener, FalsingPlugin.class);
+ }
+
+ @Override
+ public void onSucccessfulUnlock() {
+ mInternalFalsingManager.onSucccessfulUnlock();
+ }
+
+ @Override
+ public void onNotificationActive() {
+ mInternalFalsingManager.onNotificationActive();
+ }
+
+ @Override
+ public void setShowingAod(boolean showingAod) {
+ mInternalFalsingManager.setShowingAod(showingAod);
+ }
+
+ @Override
+ public void onNotificatonStartDraggingDown() {
+ mInternalFalsingManager.onNotificatonStartDraggingDown();
+ }
+
+ @Override
+ public boolean isUnlockingDisabled() {
+ return mInternalFalsingManager.isUnlockingDisabled();
+ }
+
+ @Override
+ public boolean isFalseTouch() {
+ return mInternalFalsingManager.isFalseTouch();
+ }
+
+ @Override
+ public void onNotificatonStopDraggingDown() {
+ mInternalFalsingManager.onNotificatonStartDraggingDown();
+ }
+
+ @Override
+ public void setNotificationExpanded() {
+ mInternalFalsingManager.setNotificationExpanded();
+ }
+
+ @Override
+ public boolean isClassiferEnabled() {
+ return mInternalFalsingManager.isClassiferEnabled();
+ }
+
+ @Override
+ public void onQsDown() {
+ mInternalFalsingManager.onQsDown();
+ }
+
+ @Override
+ public void setQsExpanded(boolean expanded) {
+ mInternalFalsingManager.setQsExpanded(expanded);
+ }
+
+ @Override
+ public boolean shouldEnforceBouncer() {
+ return mInternalFalsingManager.shouldEnforceBouncer();
+ }
+
+ @Override
+ public void onTrackingStarted(boolean secure) {
+ mInternalFalsingManager.onTrackingStarted(secure);
+ }
+
+ @Override
+ public void onTrackingStopped() {
+ mInternalFalsingManager.onTrackingStopped();
+ }
+
+ @Override
+ public void onLeftAffordanceOn() {
+ mInternalFalsingManager.onLeftAffordanceOn();
+ }
+
+ @Override
+ public void onCameraOn() {
+ mInternalFalsingManager.onCameraOn();
+ }
+
+ @Override
+ public void onAffordanceSwipingStarted(boolean rightCorner) {
+ mInternalFalsingManager.onAffordanceSwipingStarted(rightCorner);
+ }
+
+ @Override
+ public void onAffordanceSwipingAborted() {
+ mInternalFalsingManager.onAffordanceSwipingAborted();
+ }
+
+ @Override
+ public void onStartExpandingFromPulse() {
+ mInternalFalsingManager.onStartExpandingFromPulse();
+ }
+
+ @Override
+ public void onExpansionFromPulseStopped() {
+ mInternalFalsingManager.onExpansionFromPulseStopped();
+ }
+
+ @Override
+ public Uri reportRejectedTouch() {
+ return mInternalFalsingManager.reportRejectedTouch();
+ }
+
+ @Override
+ public void onScreenOnFromTouch() {
+ mInternalFalsingManager.onScreenOnFromTouch();
+ }
+
+ @Override
+ public boolean isReportingEnabled() {
+ return mInternalFalsingManager.isReportingEnabled();
+ }
+
+ @Override
+ public void onUnlockHintStarted() {
+ mInternalFalsingManager.onUnlockHintStarted();
+ }
+
+ @Override
+ public void onCameraHintStarted() {
+ mInternalFalsingManager.onCameraHintStarted();
+ }
+
+ @Override
+ public void onLeftAffordanceHintStarted() {
+ mInternalFalsingManager.onLeftAffordanceHintStarted();
+ }
+
+ @Override
+ public void onScreenTurningOn() {
+ mInternalFalsingManager.onScreenTurningOn();
+ }
+
+ @Override
+ public void onScreenOff() {
+ mInternalFalsingManager.onScreenOff();
+ }
+
+ @Override
+ public void onNotificatonStopDismissing() {
+ mInternalFalsingManager.onNotificatonStopDismissing();
+ }
+
+ @Override
+ public void onNotificationDismissed() {
+ mInternalFalsingManager.onNotificationDismissed();
+ }
+
+ @Override
+ public void onNotificatonStartDismissing() {
+ mInternalFalsingManager.onNotificatonStartDismissing();
+ }
+
+ @Override
+ public void onNotificationDoubleTap(boolean accepted, float dx, float dy) {
+ mInternalFalsingManager.onNotificationDoubleTap(accepted, dx, dy);
+ }
+
+ @Override
+ public void onBouncerShown() {
+ mInternalFalsingManager.onBouncerShown();
+ }
+
+ @Override
+ public void onBouncerHidden() {
+ mInternalFalsingManager.onBouncerHidden();
+ }
+
+ @Override
+ public void onTouchEvent(MotionEvent ev, int width, int height) {
+ mInternalFalsingManager.onTouchEvent(ev, width, height);
+ }
+
+ @Override
+ public void dump(PrintWriter pw) {
+ mInternalFalsingManager.dump(pw);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index 0cc50cd..86dccb2 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -151,7 +151,9 @@
}
private void addTouchEvent(MotionEvent event) {
- mClassifierData.update(event);
+ if (!mClassifierData.update(event)) {
+ return;
+ }
for (StrokeClassifier c : mStrokeClassifiers) {
c.onTouchEvent(event);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java b/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
index fb04d3e..977a2d0 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
@@ -68,4 +68,12 @@
public ArrayList<Point> getPoints() {
return mPoints;
}
+
+ public long getLastEventTimeNano() {
+ if (mPoints.isEmpty()) {
+ return mStartTimeNano;
+ }
+
+ return mPoints.get(mPoints.size() - 1).timeOffsetNano;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 5196ec6..8694d2a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -28,7 +28,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.AsyncSensorManager;
@@ -63,7 +63,7 @@
DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock);
machine.setParts(new DozeMachine.Part[]{
new DozePauser(handler, machine, alarmManager, params.getPolicy()),
- new DozeFalsingManagerAdapter(FalsingManager.getInstance(context)),
+ new DozeFalsingManagerAdapter(FalsingManagerFactory.getInstance(context)),
createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
handler, wakeLock, machine, dockManager),
createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params),
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFalsingManagerAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFalsingManagerAdapter.java
index 00ca9a4..250308d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFalsingManagerAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFalsingManagerAdapter.java
@@ -16,7 +16,7 @@
package com.android.systemui.doze;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.plugins.FalsingManager;
/**
* Notifies FalsingManager of whether or not AOD is showing.
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 68d792e..dcabb78 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -25,6 +25,7 @@
import android.app.Dialog;
import android.app.KeyguardManager;
import android.app.PendingIntent;
+import android.app.StatusBarManager;
import android.app.WallpaperManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
@@ -38,7 +39,9 @@
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.ConnectivityManager;
+import android.os.Binder;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -75,11 +78,13 @@
import com.android.internal.colorextraction.drawable.ScrimDrawable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.util.EmergencyAffordanceManager;
import com.android.internal.util.ScreenRecordHelper;
import com.android.internal.util.ScreenshotHelper;
+import com.android.internal.view.RotationPolicy;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
@@ -90,6 +95,7 @@
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.plugins.GlobalActionsPanelPlugin;
import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.UnlockMethodCache;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.EmergencyDialerConstants;
import com.android.systemui.util.leak.RotationUtils;
@@ -206,6 +212,14 @@
Dependency.get(ConfigurationController.class).addCallback(this);
mActivityStarter = Dependency.get(ActivityStarter.class);
+ UnlockMethodCache unlockMethodCache = UnlockMethodCache.getInstance(context);
+ unlockMethodCache.addListener(
+ () -> {
+ if (mDialog != null && mDialog.mPanelController != null) {
+ boolean locked = !unlockMethodCache.canSkipBouncer();
+ mDialog.mPanelController.onDeviceLockStateChanged(locked);
+ }
+ });
}
/**
@@ -413,6 +427,7 @@
},
mKeyguardManager.isDeviceLocked())
: null;
+
ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, panelViewController);
dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
dialog.setKeyguardShowing(mKeyguardShowing);
@@ -1490,6 +1505,8 @@
private final Context mContext;
private final MyAdapter mAdapter;
+ private final IStatusBarService mStatusBarService;
+ private final IBinder mToken = new Binder();
private MultiListLayout mGlobalActionsLayout;
private Drawable mBackgroundDrawable;
private final SysuiColorExtractor mColorExtractor;
@@ -1497,6 +1514,7 @@
private boolean mKeyguardShowing;
private boolean mShowing;
private float mScrimAlpha;
+ private ResetOrientationData mResetOrientationData;
ActionsDialog(Context context, MyAdapter adapter,
GlobalActionsPanelPlugin.PanelViewController plugin) {
@@ -1504,6 +1522,7 @@
mContext = context;
mAdapter = adapter;
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+ mStatusBarService = Dependency.get(IStatusBarService.class);
// Window initialization
Window window = getWindow();
@@ -1530,27 +1549,53 @@
}
private boolean shouldUsePanel() {
- if (!isPanelEnabled(mContext) || mPanelController == null) {
- return false;
- }
- if (mPanelController.getPanelContent() == null) {
- return false;
- }
- return true;
+ return mPanelController != null && mPanelController.getPanelContent() != null;
}
private void initializePanel() {
- FrameLayout panelContainer = new FrameLayout(mContext);
- FrameLayout.LayoutParams panelParams =
- new FrameLayout.LayoutParams(
- FrameLayout.LayoutParams.MATCH_PARENT,
- FrameLayout.LayoutParams.WRAP_CONTENT);
- panelContainer.addView(mPanelController.getPanelContent(), panelParams);
- addContentView(
- panelContainer,
- new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
+ int rotation = RotationUtils.getRotation(mContext);
+ boolean rotationLocked = RotationPolicy.isRotationLocked(mContext);
+ if (rotation != RotationUtils.ROTATION_NONE) {
+ if (rotationLocked) {
+ if (mResetOrientationData == null) {
+ mResetOrientationData = new ResetOrientationData();
+ mResetOrientationData.locked = true;
+ mResetOrientationData.rotation = rotation;
+ }
+
+ // Unlock rotation, so user can choose to rotate to portrait to see the panel.
+ RotationPolicy.setRotationLockAtAngle(
+ mContext, false, RotationUtils.ROTATION_NONE);
+ }
+ } else {
+ if (!rotationLocked) {
+ if (mResetOrientationData == null) {
+ mResetOrientationData = new ResetOrientationData();
+ mResetOrientationData.locked = false;
+ }
+
+ // Lock to portrait, so the user doesn't accidentally hide the panel.
+ RotationPolicy.setRotationLockAtAngle(
+ mContext, true, RotationUtils.ROTATION_NONE);
+ }
+
+ // Disable rotation suggestions, if enabled
+ setRotationSuggestionsEnabled(false);
+
+ FrameLayout panelContainer = new FrameLayout(mContext);
+ FrameLayout.LayoutParams panelParams =
+ new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT);
+ panelContainer.addView(mPanelController.getPanelContent(), panelParams);
+ addContentView(
+ panelContainer,
+ new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ mBackgroundDrawable = mPanelController.getBackgroundDrawable();
+ mScrimAlpha = 1f;
+ }
}
private void initializeLayout() {
@@ -1569,17 +1614,13 @@
mGlobalActionsLayout.setRotationListener(this::onRotate);
mGlobalActionsLayout.setAdapter(mAdapter);
- if (!shouldUsePanel()) {
- if (mBackgroundDrawable == null) {
- mBackgroundDrawable = new ScrimDrawable();
- }
- mScrimAlpha = ScrimController.GRADIENT_SCRIM_ALPHA;
- } else {
- mBackgroundDrawable = mContext.getDrawable(
- com.android.systemui.R.drawable.global_action_panel_scrim);
- mScrimAlpha = 1f;
+ if (shouldUsePanel()) {
initializePanel();
}
+ if (mBackgroundDrawable == null) {
+ mBackgroundDrawable = new ScrimDrawable();
+ mScrimAlpha = ScrimController.GRADIENT_SCRIM_ALPHA;
+ }
getWindow().setBackgroundDrawable(mBackgroundDrawable);
}
@@ -1682,19 +1723,43 @@
mBackgroundDrawable.setAlpha(alpha);
})
.start();
- if (mPanelController != null) {
- mPanelController.onDismissed();
- }
+ dismissPanel();
+ resetOrientation();
}
void dismissImmediately() {
super.dismiss();
mShowing = false;
+ dismissPanel();
+ resetOrientation();
+ }
+
+ private void dismissPanel() {
if (mPanelController != null) {
mPanelController.onDismissed();
}
}
+ private void setRotationSuggestionsEnabled(boolean enabled) {
+ try {
+ final int userId = Binder.getCallingUserHandle().getIdentifier();
+ final int what = enabled
+ ? StatusBarManager.DISABLE2_NONE
+ : StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
+ mStatusBarService.disable2ForUser(what, mToken, mContext.getPackageName(), userId);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ private void resetOrientation() {
+ if (mResetOrientationData != null) {
+ RotationPolicy.setRotationLockAtAngle(mContext, mResetOrientationData.locked,
+ mResetOrientationData.rotation);
+ }
+ setRotationSuggestionsEnabled(true);
+ }
+
@Override
public void onColorsChanged(ColorExtractor extractor, int which) {
if (mKeyguardShowing) {
@@ -1724,6 +1789,19 @@
refreshDialog();
}
}
+
+ private static class ResetOrientationData {
+ public boolean locked;
+ public int rotation;
+ }
+ }
+
+ /**
+ * Determines whether or not debug mode has been activated for the Global Actions Panel.
+ */
+ private static boolean isPanelDebugModeEnabled(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.GLOBAL_ACTIONS_PANEL_DEBUG_ENABLED, 0) == 1;
}
/**
@@ -1731,17 +1809,7 @@
* use the newer grid-style layout.
*/
private static boolean isForceGridEnabled(Context context) {
- return FeatureFlagUtils.isEnabled(context,
- FeatureFlagUtils.FORCE_GLOBAL_ACTIONS_GRID_ENABLED);
- }
-
- /**
- * Determines whether or not the Global Actions Panel should appear when the power button
- * is held.
- */
- private static boolean isPanelEnabled(Context context) {
- return FeatureFlagUtils.isEnabled(
- context, FeatureFlagUtils.GLOBAL_ACTIONS_PANEL_ENABLED);
+ return isPanelDebugModeEnabled(context);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
index 477e7d7e..24a4b9e 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
@@ -30,13 +30,15 @@
import android.util.Log;
/**
- * A helper class that computes histogram and percentile 85 from a bitmap.
- * Percentile 85 will be computed each time the user picks a new image wallpaper.
+ * A helper class that computes threshold from a bitmap.
+ * Threshold will be computed each time the user picks a new image wallpaper.
*/
class ImageProcessHelper {
private static final String TAG = ImageProcessHelper.class.getSimpleName();
- private static final float DEFAULT_PER85 = 0.8f;
- private static final int MSG_UPDATE_PER85 = 1;
+ private static final float DEFAULT_THRESHOLD = 0.8f;
+ private static final float DEFAULT_OTSU_THRESHOLD = 0f;
+ private static final float MAX_THRESHOLD = 0.89f;
+ private static final int MSG_UPDATE_THRESHOLD = 1;
/**
* This color matrix will be applied to each pixel to get luminance from rgb by below formula:
@@ -53,8 +55,8 @@
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
- case MSG_UPDATE_PER85:
- mPer85 = (float) msg.obj;
+ case MSG_UPDATE_THRESHOLD:
+ mThreshold = (float) msg.obj;
return true;
default:
return false;
@@ -62,20 +64,20 @@
}
});
- private float mPer85 = DEFAULT_PER85;
+ private float mThreshold = DEFAULT_THRESHOLD;
- void startComputingPercentile85(Bitmap bitmap) {
- new Per85ComputeTask(mHandler).execute(bitmap);
+ void start(Bitmap bitmap) {
+ new ThresholdComputeTask(mHandler).execute(bitmap);
}
- float getPercentile85() {
- return mPer85;
+ float getThreshold() {
+ return Math.min(mThreshold, MAX_THRESHOLD);
}
- private static class Per85ComputeTask extends AsyncTask<Bitmap, Void, Float> {
+ private static class ThresholdComputeTask extends AsyncTask<Bitmap, Void, Float> {
private Handler mUpdateHandler;
- Per85ComputeTask(Handler handler) {
+ ThresholdComputeTask(Handler handler) {
super(handler);
mUpdateHandler = handler;
}
@@ -84,35 +86,55 @@
protected Float doInBackground(Bitmap... bitmaps) {
Bitmap bitmap = bitmaps[0];
if (bitmap != null) {
- int[] histogram = processHistogram(bitmap);
- return computePercentile85(bitmap, histogram);
+ return new Threshold().compute(bitmap);
}
- Log.e(TAG, "Per85ComputeTask: Can't get bitmap");
- return DEFAULT_PER85;
+ Log.e(TAG, "ThresholdComputeTask: Can't get bitmap");
+ return DEFAULT_THRESHOLD;
}
@Override
protected void onPostExecute(Float result) {
- Message msg = mUpdateHandler.obtainMessage(MSG_UPDATE_PER85, result);
+ Message msg = mUpdateHandler.obtainMessage(MSG_UPDATE_THRESHOLD, result);
mUpdateHandler.sendMessage(msg);
}
+ }
- private int[] processHistogram(Bitmap bitmap) {
+ private static class Threshold {
+ public float compute(Bitmap bitmap) {
+ Bitmap grayscale = toGrayscale(bitmap);
+ int[] histogram = getHistogram(grayscale);
+ boolean isSolidColor = isSolidColor(grayscale, histogram);
+
+ // We will see gray wallpaper during the transition if solid color wallpaper is set,
+ // please refer to b/130360362#comment16.
+ // As a result, we use Percentile85 rather than Otsus if a solid color wallpaper is set.
+ ThresholdAlgorithm algorithm = isSolidColor ? new Percentile85() : new Otsus();
+ return algorithm.compute(grayscale, histogram);
+ }
+
+ private Bitmap toGrayscale(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
- Bitmap target = Bitmap.createBitmap(width, height, bitmap.getConfig());
- Canvas canvas = new Canvas(target);
+ Bitmap grayscale = Bitmap.createBitmap(width, height, bitmap.getConfig());
+ Canvas canvas = new Canvas(grayscale);
ColorMatrix cm = new ColorMatrix(LUMINOSITY_MATRIX);
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(cm));
canvas.drawBitmap(bitmap, new Matrix(), paint);
+ return grayscale;
+ }
+
+ private int[] getHistogram(Bitmap grayscale) {
+ int width = grayscale.getWidth();
+ int height = grayscale.getHeight();
+
// TODO: Fine tune the performance here, tracking on b/123615079.
int[] histogram = new int[256];
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
- int pixel = target.getPixel(col, row);
+ int pixel = grayscale.getPixel(col, row);
int y = Color.red(pixel) + Color.green(pixel) + Color.blue(pixel);
histogram[y]++;
}
@@ -121,8 +143,29 @@
return histogram;
}
- private float computePercentile85(Bitmap bitmap, int[] histogram) {
- float per85 = DEFAULT_PER85;
+ private boolean isSolidColor(Bitmap bitmap, int[] histogram) {
+ boolean solidColor = false;
+ int pixels = bitmap.getWidth() * bitmap.getHeight();
+
+ // In solid color case, only one element of histogram has value,
+ // which is pixel counts and the value of other elements should be 0.
+ for (int value : histogram) {
+ if (value != 0 && value != pixels) {
+ break;
+ }
+ if (value == pixels) {
+ solidColor = true;
+ break;
+ }
+ }
+ return solidColor;
+ }
+ }
+
+ private static class Percentile85 implements ThresholdAlgorithm {
+ @Override
+ public float compute(Bitmap bitmap, int[] histogram) {
+ float per85 = DEFAULT_THRESHOLD;
int pixelCount = bitmap.getWidth() * bitmap.getHeight();
float[] acc = new float[256];
for (int i = 0; i < acc.length; i++) {
@@ -141,4 +184,51 @@
return per85;
}
}
+
+ private static class Otsus implements ThresholdAlgorithm {
+ @Override
+ public float compute(Bitmap bitmap, int[] histogram) {
+ float threshold = DEFAULT_OTSU_THRESHOLD;
+ float maxVariance = 0;
+ float pixelCount = bitmap.getWidth() * bitmap.getHeight();
+ float[] w = new float[2];
+ float[] m = new float[2];
+ float[] u = new float[2];
+
+ for (int i = 0; i < histogram.length; i++) {
+ m[1] += i * histogram[i];
+ }
+
+ w[1] = pixelCount;
+ for (int tonalValue = 0; tonalValue < histogram.length; tonalValue++) {
+ float dU;
+ float variance;
+ float numPixels = histogram[tonalValue];
+ float tmp = numPixels * tonalValue;
+ w[0] += numPixels;
+ w[1] -= numPixels;
+
+ if (w[0] == 0 || w[1] == 0) {
+ continue;
+ }
+
+ m[0] += tmp;
+ m[1] -= tmp;
+ u[0] = m[0] / w[0];
+ u[1] = m[1] / w[1];
+ dU = u[0] - u[1];
+ variance = w[0] * w[1] * dU * dU;
+
+ if (variance > maxVariance) {
+ threshold = (tonalValue + 1f) / histogram.length;
+ maxVariance = variance;
+ }
+ }
+ return threshold;
+ }
+ }
+
+ private interface ThresholdAlgorithm {
+ float compute(Bitmap bitmap, int[] histogram);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index 464cbe3..5bbfe84 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -78,8 +78,8 @@
mBitmap = mWallpaperManager.getBitmap();
mBitmapWidth = mBitmap.getWidth();
mBitmapHeight = mBitmap.getHeight();
- // Compute per85 as transition threshold, this is an async work.
- mImageProcessHelper.startComputingPercentile85(mBitmap);
+ // Compute threshold of the image, this is an async work.
+ mImageProcessHelper.start(mBitmap);
mWallpaperManager.forgetLoadedWallpaper();
}
}
@@ -108,13 +108,13 @@
@Override
public void onDrawFrame(GL10 gl) {
- float per85 = mImageProcessHelper.getPercentile85();
+ float threshold = mImageProcessHelper.getThreshold();
float reveal = mImageRevealHelper.getReveal();
glClear(GL_COLOR_BUFFER_BIT);
glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_AOD2OPACITY), 1);
- glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_PER85), per85);
+ glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_PER85), threshold);
glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal);
scaleViewport(reveal);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 1fa6ad6..ec6cfe9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -83,7 +83,7 @@
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.UiOffloadThread;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -1594,7 +1594,7 @@
Trace.beginSection("KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj;
handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration);
- FalsingManager.getInstance(mContext).onSucccessfulUnlock();
+ FalsingManagerFactory.getInstance(mContext).onSucccessfulUnlock();
Trace.endSection();
break;
case KEYGUARD_DONE_PENDING_TIMEOUT:
@@ -1785,31 +1785,37 @@
public void run() {
Trace.beginSection("KeyguardViewMediator.mKeyGuardGoingAwayRunnable");
if (DEBUG) Log.d(TAG, "keyguardGoingAway");
- try {
- mStatusBarKeyguardViewManager.keyguardGoingAway();
+ mStatusBarKeyguardViewManager.keyguardGoingAway();
- int flags = 0;
- if (mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
- || (mWakeAndUnlocking && !mPulsing)) {
- flags |= WindowManagerPolicyConstants
- .KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
- }
- if (mStatusBarKeyguardViewManager.isGoingToNotificationShade()
- || (mWakeAndUnlocking && mPulsing)) {
- flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
- }
- if (mStatusBarKeyguardViewManager.isUnlockWithWallpaper()) {
- flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
- }
-
- mUpdateMonitor.setKeyguardGoingAway(true /* goingAway */);
- // Don't actually hide the Keyguard at the moment, wait for window
- // manager until it tells us it's safe to do so with
- // startKeyguardExitAnimation.
- ActivityTaskManager.getService().keyguardGoingAway(flags);
- } catch (RemoteException e) {
- Log.e(TAG, "Error while calling WindowManager", e);
+ int flags = 0;
+ if (mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
+ || (mWakeAndUnlocking && !mPulsing)) {
+ flags |= WindowManagerPolicyConstants
+ .KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
}
+ if (mStatusBarKeyguardViewManager.isGoingToNotificationShade()
+ || (mWakeAndUnlocking && mPulsing)) {
+ flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
+ }
+ if (mStatusBarKeyguardViewManager.isUnlockWithWallpaper()) {
+ flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
+ }
+
+ mUpdateMonitor.setKeyguardGoingAway(true /* goingAway */);
+
+ // Don't actually hide the Keyguard at the moment, wait for window
+ // manager until it tells us it's safe to do so with
+ // startKeyguardExitAnimation.
+ // Posting to mUiOffloadThread to ensure that calls to ActivityTaskManager will be in
+ // order.
+ final int keyguardFlag = flags;
+ mUiOffloadThread.submit(() -> {
+ try {
+ ActivityTaskManager.getService().keyguardGoingAway(keyguardFlag);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error while calling WindowManager", e);
+ }
+ });
Trace.endSection();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index e92aa51..f6cd199 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -353,7 +353,6 @@
if (!mHighTempWarning) {
return;
}
- mHighTempWarning = false;
dismissHighTemperatureWarningInternal();
}
@@ -364,6 +363,7 @@
*/
private void dismissHighTemperatureWarningInternal() {
mNoMan.cancelAsUser(TAG_TEMPERATURE, SystemMessage.NOTE_HIGH_TEMP, UserHandle.ALL);
+ mHighTempWarning = false;
}
@Override
@@ -575,10 +575,6 @@
d.setPositiveButton(com.android.internal.R.string.confirm_battery_saver,
(dialog, which) -> {
final ContentResolver resolver = mContext.getContentResolver();
- Secure.putInt(
- resolver,
- Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
- 1);
Settings.Global.putInt(
resolver,
Global.AUTOMATIC_POWER_SAVE_MODE,
@@ -587,6 +583,10 @@
resolver,
Global.LOW_POWER_MODE_TRIGGER_LEVEL,
batterySaverTriggerLevel);
+ Secure.putInt(
+ resolver,
+ Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
+ 1);
});
} else {
d.setTitle(R.string.battery_saver_confirmation_title);
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index b57c053..fb8b6c7 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -23,11 +23,9 @@
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.database.ContentObserver;
import android.os.BatteryManager;
import android.os.Handler;
-import android.os.IBinder;
import android.os.IThermalEventListener;
import android.os.IThermalService;
import android.os.PowerManager;
@@ -95,6 +93,9 @@
@VisibleForTesting int mBatteryLevel = 100;
@VisibleForTesting int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
+ private IThermalEventListener mSkinThermalEventListener;
+ private IThermalEventListener mUsbThermalEventListener;
+
public void start() {
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
@@ -119,7 +120,29 @@
// to the temperature being too high.
showThermalShutdownDialog();
- initTemperature();
+ // Register an observer to configure mEnableSkinTemperatureWarning and perform the
+ // registration of skin thermal event listener upon Settings change.
+ resolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.SHOW_TEMPERATURE_WARNING),
+ false /*notifyForDescendants*/,
+ new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ doSkinThermalEventListenerRegistration();
+ }
+ });
+ // Register an observer to configure mEnableUsbTemperatureAlarm and perform the
+ // registration of usb thermal event listener upon Settings change.
+ resolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.SHOW_USB_TEMPERATURE_ALARM),
+ false /*notifyForDescendants*/,
+ new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ doUsbThermalEventListenerRegistration();
+ }
+ });
+ initThermalEventListeners();
}
@Override
@@ -128,7 +151,7 @@
// Safe to modify mLastConfiguration here as it's only updated by the main thread (here).
if ((mLastConfiguration.updateFrom(newConfig) & mask) != 0) {
- mHandler.post(this::initTemperature);
+ mHandler.post(this::initThermalEventListeners);
}
}
@@ -444,45 +467,78 @@
&& currentSnapshot.getBucket() > 0);
}
- private void initTemperature() {
- ContentResolver resolver = mContext.getContentResolver();
- Resources resources = mContext.getResources();
+ private void initThermalEventListeners() {
+ doSkinThermalEventListenerRegistration();
+ doUsbThermalEventListenerRegistration();
+ }
- mEnableSkinTemperatureWarning = Settings.Global.getInt(resolver,
- Settings.Global.SHOW_TEMPERATURE_WARNING,
- resources.getInteger(R.integer.config_showTemperatureWarning)) != 0;
- mEnableUsbTemperatureAlarm = Settings.Global.getInt(resolver,
- Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
- resources.getInteger(R.integer.config_showUsbPortAlarm)) != 0;
+ @VisibleForTesting
+ synchronized void doSkinThermalEventListenerRegistration() {
+ final boolean oldEnableSkinTemperatureWarning = mEnableSkinTemperatureWarning;
+ boolean ret = false;
- if (mThermalService == null) {
- // Enable push notifications of throttling from vendor thermal
- // management subsystem via thermalservice, in addition to our
- // usual polling, to react to temperature jumps more quickly.
- IBinder b = ServiceManager.getService(Context.THERMAL_SERVICE);
+ mEnableSkinTemperatureWarning = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.SHOW_TEMPERATURE_WARNING,
+ mContext.getResources().getInteger(R.integer.config_showTemperatureWarning)) != 0;
- if (b != null) {
- mThermalService = IThermalService.Stub.asInterface(b);
- registerThermalEventListener();
- } else {
- Slog.w(TAG, "cannot find thermalservice, no throttling push notifications");
+ if (mEnableSkinTemperatureWarning != oldEnableSkinTemperatureWarning) {
+ try {
+ if (mSkinThermalEventListener == null) {
+ mSkinThermalEventListener = new SkinThermalEventListener();
+ }
+ if (mThermalService == null) {
+ mThermalService = IThermalService.Stub.asInterface(
+ ServiceManager.getService(Context.THERMAL_SERVICE));
+ }
+ if (mEnableSkinTemperatureWarning) {
+ ret = mThermalService.registerThermalEventListenerWithType(
+ mSkinThermalEventListener, Temperature.TYPE_SKIN);
+ } else {
+ ret = mThermalService.unregisterThermalEventListener(mSkinThermalEventListener);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception while (un)registering skin thermal event listener.", e);
+ }
+
+ if (!ret) {
+ mEnableSkinTemperatureWarning = !mEnableSkinTemperatureWarning;
+ Slog.e(TAG, "Failed to register or unregister skin thermal event listener.");
}
}
}
@VisibleForTesting
- void registerThermalEventListener() {
- try {
- if (mEnableSkinTemperatureWarning) {
- mThermalService.registerThermalEventListenerWithType(
- new ThermalEventSkinListener(), Temperature.TYPE_SKIN);
+ synchronized void doUsbThermalEventListenerRegistration() {
+ final boolean oldEnableUsbTemperatureAlarm = mEnableUsbTemperatureAlarm;
+ boolean ret = false;
+
+ mEnableUsbTemperatureAlarm = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
+ mContext.getResources().getInteger(R.integer.config_showUsbPortAlarm)) != 0;
+
+ if (mEnableUsbTemperatureAlarm != oldEnableUsbTemperatureAlarm) {
+ try {
+ if (mUsbThermalEventListener == null) {
+ mUsbThermalEventListener = new UsbThermalEventListener();
+ }
+ if (mThermalService == null) {
+ mThermalService = IThermalService.Stub.asInterface(
+ ServiceManager.getService(Context.THERMAL_SERVICE));
+ }
+ if (mEnableUsbTemperatureAlarm) {
+ ret = mThermalService.registerThermalEventListenerWithType(
+ mUsbThermalEventListener, Temperature.TYPE_USB_PORT);
+ } else {
+ ret = mThermalService.unregisterThermalEventListener(mUsbThermalEventListener);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception while (un)registering usb thermal event listener.", e);
}
- if (mEnableUsbTemperatureAlarm) {
- mThermalService.registerThermalEventListenerWithType(
- new ThermalEventUsbListener(), Temperature.TYPE_USB_PORT);
+
+ if (!ret) {
+ mEnableUsbTemperatureAlarm = !mEnableUsbTemperatureAlarm;
+ Slog.e(TAG, "Failed to register or unregister usb thermal event listener.");
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to register thermal callback.", e);
}
}
@@ -558,7 +614,7 @@
void showHighTemperatureWarning();
/**
- * Display USB overheat alarm
+ * Display USB port overheat alarm
*/
void showUsbHighTemperatureAlarm();
@@ -575,9 +631,9 @@
void updateSnapshot(BatteryStateSnapshot snapshot);
}
- // Thermal event received from thermal service manager subsystem
+ // Skin thermal event received from thermal service manager subsystem
@VisibleForTesting
- final class ThermalEventSkinListener extends IThermalEventListener.Stub {
+ final class SkinThermalEventListener extends IThermalEventListener.Stub {
@Override public void notifyThrottling(Temperature temp) {
int status = temp.getStatus();
@@ -585,7 +641,7 @@
StatusBar statusBar = getComponent(StatusBar.class);
if (statusBar != null && !statusBar.isDeviceInVrMode()) {
mWarnings.showHighTemperatureWarning();
- Slog.d(TAG, "ThermalEventSkinListener: notifyThrottling was called "
+ Slog.d(TAG, "SkinThermalEventListener: notifyThrottling was called "
+ ", current skin status = " + status
+ ", temperature = " + temp.getValue());
}
@@ -595,15 +651,15 @@
}
}
- // Thermal event received from thermal service manager subsystem
+ // Usb thermal event received from thermal service manager subsystem
@VisibleForTesting
- final class ThermalEventUsbListener extends IThermalEventListener.Stub {
+ final class UsbThermalEventListener extends IThermalEventListener.Stub {
@Override public void notifyThrottling(Temperature temp) {
int status = temp.getStatus();
if (status >= Temperature.THROTTLING_EMERGENCY) {
mWarnings.showUsbHighTemperatureAlarm();
- Slog.d(TAG, "ThermalEventUsbListener: notifyThrottling was called "
+ Slog.d(TAG, "UsbThermalEventListener: notifyThrottling was called "
+ ", current usb port status = " + status
+ ", temperature = " + temp.getValue());
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
deleted file mode 100644
index c1aa706..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.qs;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.service.quicksettings.Tile;
-import android.widget.ImageView;
-
-import com.android.settingslib.graph.SignalDrawable;
-import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSTile.Icon;
-import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
-
-import java.util.Objects;
-
-// Exists to provide easy way to add sim icon to cell tile
-// TODO Find a better way to handle this and remove it.
-public class CellTileView extends SignalTileView {
-
- private final SignalDrawable mSignalDrawable;
-
- public CellTileView(Context context) {
- super(context);
- mSignalDrawable = new SignalDrawable(mContext);
- mSignalDrawable.setColors(QSTileImpl.getColorForState(context, Tile.STATE_UNAVAILABLE),
- QSTileImpl.getColorForState(context, Tile.STATE_ACTIVE));
- mSignalDrawable.setIntrinsicSize(context.getResources().getDimensionPixelSize(
- R.dimen.qs_tile_icon_size));
- }
-
- protected void updateIcon(ImageView iv, State state, boolean allowAnimations) {
- if (!(state.icon instanceof SignalIcon)) {
- super.updateIcon(iv, state, allowAnimations);
- return;
- } else if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) {
- mSignalDrawable.setLevel(((SignalIcon) state.icon).getState());
- iv.setImageDrawable(mSignalDrawable);
- iv.setTag(R.id.qs_icon_tag, state.icon);
- }
- }
-
- public static class SignalIcon extends Icon {
-
- private final int mState;
-
- public SignalIcon(int state) {
- mState = state;
- }
-
- public int getState() {
- return mState;
- }
-
- @Override
- public Drawable getDrawable(Context context) {
- //TODO: Not the optimal solution to create this drawable
- SignalDrawable d = new SignalDrawable(context);
- d.setColors(QSTileImpl.getColorForState(context, Tile.STATE_UNAVAILABLE),
- QSTileImpl.getColorForState(context, Tile.STATE_ACTIVE));
- d.setLevel(getState());
- return d;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java
index fd7efc9..c5bf402 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java
@@ -75,12 +75,11 @@
mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE);
if (state.visible) {
mMobileRoaming.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
- mMobileRoaming.setImageTintList(ColorStateList.valueOf(
- mDualToneHandler.getSingleColor(mColorForegroundIntensity)));
- SignalDrawable d = new SignalDrawable(mContext);
- d.setColors(mDualToneHandler.getBackgroundColor(mColorForegroundIntensity),
- mDualToneHandler.getFillColor(mColorForegroundIntensity));
- mMobileSignal.setImageDrawable(d);
+ ColorStateList colorStateList = ColorStateList.valueOf(
+ mDualToneHandler.getSingleColor(mColorForegroundIntensity));
+ mMobileRoaming.setImageTintList(colorStateList);
+ mMobileSignal.setImageDrawable(new SignalDrawable(mContext));
+ mMobileSignal.setImageTintList(colorStateList);
mMobileSignal.setImageLevel(state.mobileSignalIconId);
StringBuilder contentDescription = new StringBuilder();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
index e352b58..4571ef3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
@@ -77,6 +77,7 @@
@Override
public void onClick(View v) {
+ if (!v.isVisibleToUser()) return;
mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
Settings.ACTION_WIRELESS_SETTINGS), 0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 9431f20..42c616c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -524,7 +524,7 @@
if (v == mClockView) {
mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
AlarmClock.ACTION_SHOW_ALARMS), 0);
- } else if (v == mNextAlarmContainer) {
+ } else if (v == mNextAlarmContainer && mNextAlarmContainer.isVisibleToUser()) {
if (mNextAlarm.getShowIntent() != null) {
mActivityStarter.postStartActivityDismissingKeyguard(
mNextAlarm.getShowIntent());
@@ -545,7 +545,7 @@
new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
mHost.collapsePanels();
});
- } else if (v == mRingerContainer) {
+ } else if (v == mRingerContainer && mRingerContainer.isVisibleToUser()) {
mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
Settings.ACTION_SOUND_SETTINGS), 0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 8aacd72..14addb9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -126,7 +126,7 @@
(mRows != 0 ? (mCellMarginTop - mCellMarginVertical) : 0);
if (height < 0) height = 0;
- setMeasuredDimension(width + getPaddingStart() + getPaddingEnd(), height);
+ setMeasuredDimension(width, height);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 416c2da..2a7e55f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -69,6 +69,7 @@
// Whether we have a pending bind going out to the service without a response yet.
// This defaults to true to ensure tiles start out unavailable.
private boolean mPendingBind = true;
+ private boolean mStarted = false;
TileServiceManager(TileServices tileServices, Handler handler, ComponentName component,
Tile tile) {
@@ -90,7 +91,23 @@
Context context = mServices.getContext();
context.registerReceiverAsUser(mUninstallReceiver,
new UserHandle(ActivityManager.getCurrentUser()), filter, null, mHandler);
- ComponentName component = tileLifecycleManager.getComponent();
+ }
+
+ boolean isLifecycleStarted() {
+ return mStarted;
+ }
+
+ /**
+ * Starts the TileLifecycleManager by adding the corresponding component as a Tile and
+ * binding to it if needed.
+ *
+ * This method should be called after constructing a TileServiceManager to guarantee that the
+ * TileLifecycleManager has added the tile and bound to it at least once.
+ */
+ void startLifecycleManagerAndAddTile() {
+ mStarted = true;
+ ComponentName component = mStateManager.getComponent();
+ Context context = mServices.getContext();
if (!TileLifecycleManager.isTileAdded(context, component)) {
TileLifecycleManager.setTileAdded(context, component, true);
mStateManager.onTileAdded();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 6f664d7..23f36e9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -51,6 +51,7 @@
public class TileServices extends IQSService.Stub {
static final int DEFAULT_MAX_BOUND = 3;
static final int REDUCED_MAX_BOUND = 1;
+ private static final String TAG = "TileServices";
private final ArrayMap<CustomTile, TileServiceManager> mServices = new ArrayMap<>();
private final ArrayMap<ComponentName, CustomTile> mTiles = new ArrayMap<>();
@@ -87,6 +88,8 @@
mTiles.put(component, tile);
mTokenMap.put(service.getToken(), tile);
}
+ // Makes sure binding only happens after the maps have been populated
+ service.startLifecycleManagerAndAddTile();
return service;
}
@@ -179,6 +182,11 @@
verifyCaller(customTile);
synchronized (mServices) {
final TileServiceManager tileServiceManager = mServices.get(customTile);
+ if (tileServiceManager == null || !tileServiceManager.isLifecycleStarted()) {
+ Log.e(TAG, "TileServiceManager not started for " + customTile.getComponent(),
+ new IllegalStateException());
+ return;
+ }
tileServiceManager.clearPendingBind();
tileServiceManager.setLastUpdate(System.currentTimeMillis());
}
@@ -194,6 +202,13 @@
verifyCaller(customTile);
synchronized (mServices) {
final TileServiceManager tileServiceManager = mServices.get(customTile);
+ // This should not happen as the TileServiceManager should have been started for the
+ // first bind to happen.
+ if (tileServiceManager == null || !tileServiceManager.isLifecycleStarted()) {
+ Log.e(TAG, "TileServiceManager not started for " + customTile.getComponent(),
+ new IllegalStateException());
+ return;
+ }
tileServiceManager.clearPendingBind();
}
customTile.refreshState();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index ca04076..9282a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -144,7 +144,8 @@
mContext.getString(R.string.accessibility_bluetooth_name, state.label)
+ ", " + state.secondaryLabel;
} else if (state.isTransient) {
- state.icon = ResourceIcon.get(R.drawable.ic_bluetooth_transient_animation);
+ state.icon = ResourceIcon.get(
+ com.android.internal.R.drawable.ic_bluetooth_transient_animation);
state.contentDescription = state.secondaryLabel;
} else {
state.icon =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 20e002e..20069ea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -40,9 +40,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
-import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile.SignalState;
-import com.android.systemui.qs.CellTileView;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -89,11 +87,6 @@
}
@Override
- public QSIconView createTileView(Context context) {
- return new CellTileView(context);
- }
-
- @Override
public Intent getLongClickIntent() {
return getCellularSettingIntent();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 5e6f18e..001e094 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -130,7 +130,8 @@
state.isTransient = isTransient;
state.slash.isSlashed = !state.value && !state.isTransient;
if (state.isTransient) {
- state.icon = ResourceIcon.get(R.drawable.ic_hotspot_transient_animation);
+ state.icon = ResourceIcon.get(
+ com.android.internal.R.drawable.ic_hotspot_transient_animation);
}
state.expandedAccessibilityClassName = Switch.class.getName();
state.contentDescription = state.label;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
index f26a94f..dd0ea5e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
@@ -28,6 +28,7 @@
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import javax.inject.Inject;
@@ -39,17 +40,22 @@
* taken by {@link NightDisplayTile}.
*/
public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements
- ConfigurationController.ConfigurationListener {
+ ConfigurationController.ConfigurationListener,
+ BatteryController.BatteryStateChangeCallback {
private final Icon mIcon = ResourceIcon.get(
com.android.internal.R.drawable.ic_qs_ui_mode_night);
- private UiModeManager mUiModeManager;
+ private final UiModeManager mUiModeManager;
+ private final BatteryController mBatteryController;
@Inject
- public UiModeNightTile(QSHost host, ConfigurationController configurationController) {
+ public UiModeNightTile(QSHost host, ConfigurationController configurationController,
+ BatteryController batteryController) {
super(host);
+ mBatteryController = batteryController;
mUiModeManager = mContext.getSystemService(UiModeManager.class);
configurationController.observe(getLifecycle(), this);
+ batteryController.observe(getLifecycle(), this);
}
@Override
@@ -58,12 +64,20 @@
}
@Override
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ refreshState();
+ }
+
+ @Override
public BooleanState newTileState() {
return new BooleanState();
}
@Override
protected void handleClick() {
+ if (getState().state == Tile.STATE_UNAVAILABLE) {
+ return;
+ }
boolean newState = !mState.value;
mUiModeManager.setNightMode(newState ? UiModeManager.MODE_NIGHT_YES
: UiModeManager.MODE_NIGHT_NO);
@@ -72,15 +86,22 @@
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
+ boolean powerSave = mBatteryController.isPowerSave();
boolean nightMode = (mContext.getResources().getConfiguration().uiMode
& Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
state.value = nightMode;
- state.label = mContext.getString(R.string.quick_settings_ui_mode_night_label);
+ state.label = mContext.getString(powerSave
+ ? R.string.quick_settings_ui_mode_night_label_battery_saver
+ : R.string.quick_settings_ui_mode_night_label);
state.contentDescription = state.label;
state.icon = mIcon;
state.expandedAccessibilityClassName = Switch.class.getName();
- state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+ if (powerSave) {
+ state.state = Tile.STATE_UNAVAILABLE;
+ } else {
+ state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+ }
state.showRippleEffect = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 15df1f1..0e7362c3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -186,7 +186,8 @@
final StringBuffer minimalContentDescription = new StringBuffer();
final Resources r = mContext.getResources();
if (isTransient) {
- state.icon = ResourceIcon.get(R.drawable.ic_signal_wifi_transient_animation);
+ state.icon = ResourceIcon.get(
+ com.android.internal.R.drawable.ic_signal_wifi_transient_animation);
state.label = r.getString(R.string.quick_settings_wifi_label);
} else if (!state.value) {
state.slash.isSlashed = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CastDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/CastDrawable.java
new file mode 100644
index 0000000..2f385d0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CastDrawable.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableWrapper;
+import android.util.AttributeSet;
+
+import com.android.systemui.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * The status bar cast drawable draws ic_cast and ic_cast_connected_fill to indicate that the
+ * screen is being recorded. A simple layer-list drawable isn't used here because the record fill
+ * must not be tinted by the caller.
+ */
+public class CastDrawable extends DrawableWrapper {
+ private Drawable mFillDrawable;
+ private int mHorizontalPadding;
+
+ /** No-arg constructor used by drawable inflation. */
+ public CastDrawable() {
+ super(null);
+ }
+
+ @Override
+ public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
+ @NonNull AttributeSet attrs, @Nullable Resources.Theme theme)
+ throws XmlPullParserException, IOException {
+ super.inflate(r, parser, attrs, theme);
+ setDrawable(r.getDrawable(R.drawable.ic_cast, theme).mutate());
+ mFillDrawable = r.getDrawable(R.drawable.ic_cast_connected_fill, theme).mutate();
+ mHorizontalPadding = r.getDimensionPixelSize(R.dimen.status_bar_horizontal_padding);
+ }
+
+ @Override
+ public boolean canApplyTheme() {
+ return mFillDrawable.canApplyTheme() || super.canApplyTheme();
+ }
+
+ @Override
+ public void applyTheme(Resources.Theme t) {
+ super.applyTheme(t);
+ mFillDrawable.applyTheme(t);
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ super.onBoundsChange(bounds);
+ mFillDrawable.setBounds(bounds);
+ }
+
+ @Override
+ public boolean onLayoutDirectionChanged(int layoutDirection) {
+ mFillDrawable.setLayoutDirection(layoutDirection);
+ return super.onLayoutDirectionChanged(layoutDirection);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+ mFillDrawable.draw(canvas);
+ }
+
+ @Override
+ public boolean getPadding(Rect padding) {
+ padding.left += mHorizontalPadding;
+ padding.right += mHorizontalPadding;
+ return true;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ super.setAlpha(alpha);
+ mFillDrawable.setAlpha(alpha);
+ }
+
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ mFillDrawable.setVisible(visible, restart);
+ return super.setVisible(visible, restart);
+ }
+
+ @Override
+ public Drawable mutate() {
+ mFillDrawable.mutate();
+ return super.mutate();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 9f8ab61..f97be1ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -78,7 +78,7 @@
private static final int MSG_COLLAPSE_PANELS = 4 << MSG_SHIFT;
private static final int MSG_EXPAND_SETTINGS = 5 << MSG_SHIFT;
private static final int MSG_SET_SYSTEMUI_VISIBILITY = 6 << MSG_SHIFT;
- private static final int MSG_TOP_APP_WINDOW_CHANGED = 7 << MSG_SHIFT;
+ private static final int MSG_DISPLAY_READY = 7 << MSG_SHIFT;
private static final int MSG_SHOW_IME_BUTTON = 8 << MSG_SHIFT;
private static final int MSG_TOGGLE_RECENT_APPS = 9 << MSG_SHIFT;
private static final int MSG_PRELOAD_RECENT_APPS = 10 << MSG_SHIFT;
@@ -115,7 +115,6 @@
private static final int MSG_SHOW_CHARGING_ANIMATION = 44 << MSG_SHIFT;
private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
private static final int MSG_SHOW_PINNING_TOAST_ESCAPE = 46 << MSG_SHIFT;
- private static final int MSG_DISPLAY_READY = 47 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -183,15 +182,6 @@
}
/**
- * Called to notify top app window changes.
- * @see IStatusBar#topAppWindowChanged(int, boolean)
- *
- * @param displayId The id of the display to notify.
- * @param visible {@code true} to show menu button.
- */
- default void topAppWindowChanged(int displayId, boolean visible) { }
-
- /**
* Called to notify IME window status changes.
*
* @param displayId The id of the display to notify.
@@ -480,13 +470,7 @@
}
@Override
- public void topAppWindowChanged(int displayId, boolean menuVisible) {
- synchronized (mLock) {
- mHandler.removeMessages(MSG_TOP_APP_WINDOW_CHANGED);
- mHandler.obtainMessage(MSG_TOP_APP_WINDOW_CHANGED,
- displayId, menuVisible ? 1 : 0, null).sendToTarget();
- }
- }
+ public void topAppWindowChanged(int displayId, boolean menuVisible) { }
@Override
public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
@@ -888,11 +872,6 @@
}
args.recycle();
break;
- case MSG_TOP_APP_WINDOW_CHANGED:
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).topAppWindowChanged(msg.arg1, msg.arg2 != 0);
- }
- break;
case MSG_SHOW_IME_BUTTON:
args = (SomeArgs) msg.obj;
handleShowImeButton(args.argi1 /* displayId */, (IBinder) args.arg1 /* token */,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 8a86826..514a2ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -29,7 +29,8 @@
import com.android.systemui.Gefingerpoken;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.notification.row.ExpandableView;
/**
@@ -65,7 +66,7 @@
mCallback = callback;
mDragDownCallback = dragDownCallback;
mHost = host;
- mFalsingManager = FalsingManager.getInstance(context);
+ mFalsingManager = FalsingManagerFactory.getInstance(context);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index fcbb416..a76c9dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -198,7 +198,7 @@
if (!mAccessibilityController.isAccessibilityEnabled()) {
return;
}
- mShadeController.showBouncer(false /* scrimmed */);
+ mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
index b7ae4ed..4b2d131 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar
-import android.annotation.ColorInt
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
@@ -28,6 +27,7 @@
import android.renderscript.ScriptIntrinsicBlur
import android.util.MathUtils
import com.android.internal.graphics.ColorUtils
+import com.android.systemui.statusbar.notification.MediaNotificationProcessor
import javax.inject.Inject
import javax.inject.Singleton
@@ -42,7 +42,7 @@
private val mTmpSize = Point()
private var mArtworkCache: Bitmap? = null
- fun processArtwork(context: Context, artwork: Bitmap, @ColorInt color: Int): Bitmap {
+ fun processArtwork(context: Context, artwork: Bitmap): Bitmap {
if (mArtworkCache != null) {
return mArtworkCache!!
}
@@ -71,13 +71,15 @@
blur.forEach(output)
output.copyTo(outBitmap)
+ val swatch = MediaNotificationProcessor.findBackgroundSwatch(artwork)
+
input.destroy()
output.destroy()
inBitmap.recycle()
blur.destroy()
val canvas = Canvas(outBitmap)
- canvas.drawColor(ColorUtils.setAlphaComponent(color, COLOR_ALPHA))
+ canvas.drawColor(ColorUtils.setAlphaComponent(swatch.rgb, COLOR_ALPHA))
return outBitmap
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index bd25209..7bcbd36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -32,6 +32,8 @@
import android.view.View;
import android.view.WindowManagerGlobal;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.RegisterStatusBarResult;
import com.android.systemui.Dependency;
@@ -213,8 +215,17 @@
}
/** @return {@link NavigationBarView} on the default display. */
- public NavigationBarView getDefaultNavigationBarView() {
- NavigationBarFragment navBar = mNavigationBars.get(DEFAULT_DISPLAY);
+ public @Nullable NavigationBarView getDefaultNavigationBarView() {
+ return getNavigationBarView(DEFAULT_DISPLAY);
+ }
+
+ /**
+ * @param displayId the ID of display which Navigation bar is on
+ * @return {@link NavigationBarView} on the display with {@code displayId}.
+ * {@code null} if no navigation bar on that display.
+ */
+ public @Nullable NavigationBarView getNavigationBarView(int displayId) {
+ NavigationBarFragment navBar = mNavigationBars.get(displayId);
return (navBar == null) ? null : (NavigationBarView) navBar.getView();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index aeaceb0..9d5871e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;
import static com.android.systemui.statusbar.RemoteInputController.processForRemoteInput;
+import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_CHILD_NOTIFICATIONS;
@@ -104,7 +105,7 @@
// Remove existing notification to avoid stale data.
if (isUpdate) {
- mEntryManager.removeNotification(key, rankingMap);
+ mEntryManager.removeNotification(key, rankingMap, UNDEFINED_DISMISS_REASON);
} else {
mEntryManager.getNotificationData()
.updateRanking(rankingMap);
@@ -121,18 +122,23 @@
}
@Override
- public void onNotificationRemoved(StatusBarNotification sbn,
- final RankingMap rankingMap) {
- if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
+ public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
+ int reason) {
+ if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn + " reason: " + reason);
if (sbn != null && !onPluginNotificationRemoved(sbn, rankingMap)) {
final String key = sbn.getKey();
Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
- mEntryManager.removeNotification(key, rankingMap);
+ mEntryManager.removeNotification(key, rankingMap, reason);
});
}
}
@Override
+ public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
+ onNotificationRemoved(sbn, rankingMap, UNDEFINED_DISMISS_REASON);
+ }
+
+ @Override
public void onNotificationRankingUpdate(final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onRankingUpdate");
if (rankingMap != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 1615e65..b9e0c60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -21,11 +21,11 @@
import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_WALLPAPER;
import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK;
+import android.annotation.MainThread;
import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
import android.graphics.Bitmap;
-import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -35,11 +35,13 @@
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
+import android.os.AsyncTask;
import android.os.Handler;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
+import android.util.ArraySet;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
@@ -64,8 +66,10 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -108,6 +112,7 @@
private final MediaSessionManager mMediaSessionManager;
private final ArrayList<MediaListener> mMediaListeners;
private final MediaArtworkProcessor mMediaArtworkProcessor;
+ private final Set<AsyncTask<?, ?, ?>> mProcessArtworkTasks = new ArraySet<>();
protected NotificationPresenter mPresenter;
private MediaController mMediaController;
@@ -449,28 +454,37 @@
+ " state=" + mStatusBarStateController.getState());
}
- Drawable artworkDrawable = null;
+ Bitmap artworkBitmap = null;
if (mediaMetadata != null) {
- Bitmap artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
+ artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
if (artworkBitmap == null) {
artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
- // might still be null
}
- if (artworkBitmap != null) {
- int notificationColor;
- synchronized (mEntryManager.getNotificationData()) {
- NotificationEntry entry = mEntryManager.getNotificationData()
- .get(mMediaNotificationKey);
- if (entry == null || entry.getRow() == null) {
- notificationColor = Color.TRANSPARENT;
- } else {
- notificationColor = entry.getRow().calculateBgColor();
- }
- }
- Bitmap bmp = mMediaArtworkProcessor.processArtwork(mContext, artworkBitmap,
- notificationColor);
- artworkDrawable = new BitmapDrawable(mBackdropBack.getResources(), bmp);
+ }
+
+ // Process artwork on a background thread and send the resulting bitmap to
+ // finishUpdateMediaMetaData.
+ if (metaDataChanged) {
+ for (AsyncTask<?, ?, ?> task : mProcessArtworkTasks) {
+ task.cancel(true);
}
+ mProcessArtworkTasks.clear();
+ }
+ if (artworkBitmap != null) {
+ mProcessArtworkTasks.add(new ProcessArtworkTask(this, metaDataChanged,
+ allowEnterAnimation).execute(artworkBitmap));
+ } else {
+ finishUpdateMediaMetaData(metaDataChanged, allowEnterAnimation, null);
+ }
+
+ Trace.endSection();
+ }
+
+ private void finishUpdateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation,
+ @Nullable Bitmap bmp) {
+ Drawable artworkDrawable = null;
+ if (bmp != null) {
+ artworkDrawable = new BitmapDrawable(mBackdropBack.getResources(), bmp);
}
boolean allowWhenShade = false;
if (ENABLE_LOCKSCREEN_WALLPAPER && artworkDrawable == null) {
@@ -598,7 +612,6 @@
}
}
}
- Trace.endSection();
}
public void setup(BackDropView backdrop, ImageView backdropFront, ImageView backdropBack,
@@ -629,6 +642,61 @@
}
};
+ private Bitmap processArtwork(Bitmap artwork) {
+ return mMediaArtworkProcessor.processArtwork(mContext, artwork);
+ }
+
+ @MainThread
+ private void removeTask(AsyncTask<?, ?, ?> task) {
+ mProcessArtworkTasks.remove(task);
+ }
+
+ /**
+ * {@link AsyncTask} to prepare album art for use as backdrop on lock screen.
+ */
+ private static final class ProcessArtworkTask extends AsyncTask<Bitmap, Void, Bitmap> {
+
+ private final WeakReference<NotificationMediaManager> mManagerRef;
+ private final boolean mMetaDataChanged;
+ private final boolean mAllowEnterAnimation;
+
+ ProcessArtworkTask(NotificationMediaManager manager, boolean changed,
+ boolean allowAnimation) {
+ mManagerRef = new WeakReference<>(manager);
+ mMetaDataChanged = changed;
+ mAllowEnterAnimation = allowAnimation;
+ }
+
+ @Override
+ protected Bitmap doInBackground(Bitmap... bitmaps) {
+ NotificationMediaManager manager = mManagerRef.get();
+ if (manager == null || bitmaps.length == 0 || isCancelled()) {
+ return null;
+ }
+ return manager.processArtwork(bitmaps[0]);
+ }
+
+ @Override
+ protected void onPostExecute(@Nullable Bitmap result) {
+ NotificationMediaManager manager = mManagerRef.get();
+ if (manager != null && !isCancelled()) {
+ manager.removeTask(this);
+ manager.finishUpdateMediaMetaData(mMetaDataChanged, mAllowEnterAnimation, result);
+ }
+ }
+
+ @Override
+ protected void onCancelled(Bitmap result) {
+ if (result != null) {
+ result.recycle();
+ }
+ NotificationMediaManager manager = mManagerRef.get();
+ if (manager != null) {
+ manager.removeTask(this);
+ }
+ }
+ }
+
public interface MediaListener {
void onMetadataChanged(MediaMetadata metadata);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 2793b2a..fe8c6b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -51,6 +51,7 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dumpable;
+import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -273,10 +274,20 @@
notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
+ public void onPreEntryUpdated(NotificationEntry entry) {
+ // Mark smart replies as sent whenever a notification is updated - otherwise the
+ // smart replies are never marked as sent.
+ mSmartReplyController.stopSending(entry);
+ }
+
+ @Override
public void onEntryRemoved(
@Nullable NotificationEntry entry,
NotificationVisibility visibility,
boolean removedByUser) {
+ // We're removing the notification, the smart controller can forget about it.
+ mSmartReplyController.stopSending(entry);
+
if (removedByUser && entry != null) {
onPerformRemoveNotification(entry, entry.key);
}
@@ -348,24 +359,18 @@
ViewParent p = view.getParent();
RemoteInputView riv = null;
+ ExpandableNotificationRow row = null;
while (p != null) {
if (p instanceof View) {
View pv = (View) p;
if (pv.isRootNamespace()) {
riv = findRemoteInputView(pv);
+ row = (ExpandableNotificationRow) pv.getTag(R.id.row_tag_for_content_view);
break;
}
}
p = p.getParent();
}
- ExpandableNotificationRow row = null;
- while (p != null) {
- if (p instanceof ExpandableNotificationRow) {
- row = (ExpandableNotificationRow) p;
- break;
- }
- p = p.getParent();
- }
if (row == null) {
return false;
@@ -391,10 +396,13 @@
if (riv == null) {
return false;
}
- if (!row.getPrivateLayout().getExpandedChild().isShown()) {
- mCallback.onMakeExpandedVisibleForRemoteInput(row, view);
- return true;
- }
+ }
+ if (riv == row.getPrivateLayout().getExpandedRemoteInput()
+ && !row.getPrivateLayout().getExpandedChild().isShown()) {
+ // The expanded layout is selected, but it's not shown yet, let's wait on it to
+ // show before we do the animation.
+ mCallback.onMakeExpandedVisibleForRemoteInput(row, view);
+ return true;
}
int width = view.getWidth();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoveInterceptor.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoveInterceptor.java
new file mode 100644
index 0000000..930116e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoveInterceptor.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.service.notification.NotificationListenerService;
+
+/**
+ * Interface for anything that may need to prevent notifications from being removed. This is
+ * similar to a {@link NotificationLifetimeExtender} in the sense that it extends the life of
+ * a notification by preventing the removal, however, unlike the extender, the remove interceptor
+ * gets first pick at intercepting any type of removal -- the life time extender is unable to
+ * extend the life of a user dismissed or force removed notification.
+ */
+public interface NotificationRemoveInterceptor {
+
+ /**
+ * Called when a notification has been removed.
+ *
+ * @param key the entry key of the notification being removed.
+ * @param removeReason why the notification is being removed, e.g.
+ * {@link NotificationListenerService#REASON_CANCEL} or 0 if unknown.
+ *
+ * @return true if the removal should be ignored, false otherwise.
+ */
+ boolean onNotificationRemoveRequested(String key, int removeReason);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 2cca701..d202190 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -71,6 +71,7 @@
private int mIconAppearTopPadding;
private int mShelfAppearTranslation;
private float mDarkShelfPadding;
+ private float mDarkShelfIconSize;
private int mStatusBarHeight;
private int mStatusBarPaddingStart;
private AmbientState mAmbientState;
@@ -151,6 +152,7 @@
mScrollFastThreshold = res.getDimensionPixelOffset(R.dimen.scroll_fast_threshold);
mShowNotificationShelf = res.getBoolean(R.bool.config_showNotificationShelf);
mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
+ mDarkShelfIconSize = res.getDimensionPixelOffset(R.dimen.dark_shelf_icon_size);
mGapHeight = res.getDimensionPixelSize(R.dimen.qs_notification_padding);
if (!mShowNotificationShelf) {
@@ -705,12 +707,13 @@
}
notificationIconPosition += iconTopPadding;
float shelfIconPosition = getTranslationY() + icon.getTop();
- shelfIconPosition += (icon.getHeight() - icon.getIconScale() * mIconSize) / 2.0f;
+ float iconSize = mDark ? mDarkShelfIconSize : mIconSize;
+ shelfIconPosition += (icon.getHeight() - icon.getIconScale() * iconSize) / 2.0f;
float iconYTranslation = NotificationUtils.interpolate(
notificationIconPosition - shelfIconPosition,
0,
transitionAmount);
- float shelfIconSize = mIconSize * icon.getIconScale();
+ float shelfIconSize = iconSize * icon.getIconScale();
float alpha = 1.0f;
boolean noIcon = !row.isShowingIcon();
if (noIcon) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUpdateHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUpdateHandler.java
index 0044194..1ac8198 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUpdateHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUpdateHandler.java
@@ -37,8 +37,10 @@
*
* @param key Key identifying the notification to remove
* @param ranking RankingMap to update with
+ * @param reason why the notification is being removed, e.g.
+ * {@link NotificationListenerService#REASON_CANCEL}.
*/
- void removeNotification(String key, NotificationListenerService.RankingMap ranking);
+ void removeNotification(String key, NotificationListenerService.RankingMap ranking, int reason);
/**
* Update a given notification and the current notification ranking map.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index e5dbcd3..bf99474 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -30,7 +30,8 @@
import com.android.systemui.Gefingerpoken
import com.android.systemui.Interpolators
import com.android.systemui.R
-import com.android.systemui.classifier.FalsingManager
+import com.android.systemui.classifier.FalsingManagerFactory
+import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
@@ -81,7 +82,7 @@
mMinDragDistance = context.resources.getDimensionPixelSize(
R.dimen.keyguard_drag_down_min_distance)
mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop.toFloat()
- mFalsingManager = FalsingManager.getInstance(context)
+ mFalsingManager = FalsingManagerFactory.getInstance(context)
mPowerManager = context.getSystemService(PowerManager::class.java)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index acacc8f..033c4fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -40,6 +40,7 @@
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
import android.util.FloatProperty;
import android.util.Log;
import android.util.Property;
@@ -73,7 +74,10 @@
* want to scale them (in a way that doesn't require an asset dump) down 2dp. So
* 17dp * (15 / 17) = 15dp, the new height.
*/
- private static final float SYSTEM_ICON_SCALE = 15.f / 17.f;
+ private static final float SYSTEM_ICON_DESIRED_HEIGHT = 15f;
+ private static final float SYSTEM_ICON_INTRINSIC_HEIGHT = 17f;
+ private static final float SYSTEM_ICON_SCALE =
+ SYSTEM_ICON_DESIRED_HEIGHT / SYSTEM_ICON_INTRINSIC_HEIGHT;
private final int ANIMATION_DURATION_FAST = 100;
public static final int STATE_ICON = 0;
@@ -202,8 +206,25 @@
updatePivot();
}
+ // Makes sure that all icons are scaled to the same height (15dp). If we cannot get a height
+ // for the icon, it uses the default SCALE (15f / 17f) which is the old behavior
private void updateIconScaleForSystemIcons() {
- mIconScale = SYSTEM_ICON_SCALE;
+ float iconHeight = getIconHeightInDps();
+ if (iconHeight != 0) {
+ mIconScale = SYSTEM_ICON_DESIRED_HEIGHT / iconHeight;
+ } else {
+ mIconScale = SYSTEM_ICON_SCALE;
+ }
+ }
+
+ private float getIconHeightInDps() {
+ Drawable d = getDrawable();
+ if (d != null) {
+ return ((float) getDrawable().getIntrinsicHeight() * DisplayMetrics.DENSITY_DEFAULT)
+ / mDensity;
+ } else {
+ return SYSTEM_ICON_INTRINSIC_HEIGHT;
+ }
}
public float getIconScaleFullyDark() {
@@ -221,8 +242,8 @@
if (density != mDensity) {
mDensity = density;
reloadDimens();
- maybeUpdateIconScaleDimens();
updateDrawable();
+ maybeUpdateIconScaleDimens();
}
boolean nightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK)
== Configuration.UI_MODE_NIGHT_YES;
@@ -305,6 +326,8 @@
if (!updateDrawable(false /* no clear */)) return false;
// we have to clear the grayscale tag since it may have changed
setTag(R.id.icon_is_grayscale, null);
+ // Maybe set scale based on icon height
+ maybeUpdateIconScaleDimens();
}
if (!levelEquals) {
setImageLevel(icon.iconLevel);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index 9c6b3be..812c9a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -211,8 +211,8 @@
if (!isInArea(area, this)) {
return;
}
- mMobileDrawable.setColors(mDualToneHandler.getBackgroundColor(darkIntensity),
- mDualToneHandler.getFillColor(darkIntensity));
+ mMobileDrawable.setTintList(
+ ColorStateList.valueOf(mDualToneHandler.getFillColor(darkIntensity)));
ColorStateList color = ColorStateList.valueOf(getTint(area, this, tint));
mIn.setImageTintList(color);
mOut.setImageTintList(color);
@@ -237,8 +237,8 @@
float intensity = color == Color.WHITE ? 0 : 1;
// We want the ability to change the theme from the one set by SignalDrawable in certain
// surfaces. In this way, we can pass a theme to the view.
- mMobileDrawable.setColors(mDualToneHandler.getBackgroundColor(intensity),
- mDualToneHandler.getFillColor(intensity));
+ mMobileDrawable.setTintList(
+ ColorStateList.valueOf(mDualToneHandler.getFillColor(intensity)));
mIn.setImageTintList(list);
mOut.setImageTintList(list);
mMobileType.setImageTintList(list);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
index ab94008..5d1ab4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
@@ -69,8 +69,7 @@
private static final int RESIZE_BITMAP_AREA = 150 * 150;
private final ImageGradientColorizer mColorizer;
private final Context mContext;
- private float[] mFilteredBackgroundHsl = null;
- private Palette.Filter mBlackWhiteFilter = (rgb, hsl) -> !isWhiteOrBlack(hsl);
+ private final Palette.Filter mBlackWhiteFilter = (rgb, hsl) -> !isWhiteOrBlack(hsl);
/**
* The context of the notification. This is the app context of the package posting the
@@ -121,23 +120,21 @@
drawable.setBounds(0, 0, width, height);
drawable.draw(canvas);
- // for the background we only take the left side of the image to ensure
- // a smooth transition
- Palette.Builder paletteBuilder = Palette.from(bitmap)
- .setRegion(0, 0, bitmap.getWidth() / 2, bitmap.getHeight())
- .clearFilters() // we want all colors, red / white / black ones too!
- .resizeBitmapArea(RESIZE_BITMAP_AREA);
+ Palette.Builder paletteBuilder = generateArtworkPaletteBuilder(bitmap);
Palette palette = paletteBuilder.generate();
- backgroundColor = findBackgroundColorAndFilter(palette);
+ Palette.Swatch backgroundSwatch = findBackgroundSwatch(palette);
+ backgroundColor = backgroundSwatch.getRgb();
// we want most of the full region again, slightly shifted to the right
float textColorStartWidthFraction = 0.4f;
paletteBuilder.setRegion((int) (bitmap.getWidth() * textColorStartWidthFraction), 0,
bitmap.getWidth(),
bitmap.getHeight());
- if (mFilteredBackgroundHsl != null) {
+ // We're not filtering on white or black
+ if (!isWhiteOrBlack(backgroundSwatch.getHsl())) {
+ final float backgroundHue = backgroundSwatch.getHsl()[0];
paletteBuilder.addFilter((rgb, hsl) -> {
// at least 10 degrees hue difference
- float diff = Math.abs(hsl[0] - mFilteredBackgroundHsl[0]);
+ float diff = Math.abs(hsl[0] - backgroundHue);
return diff > 10 && diff < 350;
});
}
@@ -244,18 +241,31 @@
&& (swatch.getPopulation() / (float) RESIZE_BITMAP_AREA > MINIMUM_IMAGE_FRACTION);
}
- private int findBackgroundColorAndFilter(Palette palette) {
+ /**
+ * Finds an appropriate background swatch from media artwork.
+ *
+ * @param artwork Media artwork
+ * @return Swatch that should be used as the background of the media notification.
+ */
+ public static Palette.Swatch findBackgroundSwatch(Bitmap artwork) {
+ return findBackgroundSwatch(generateArtworkPaletteBuilder(artwork).generate());
+ }
+
+ /**
+ * Finds an appropriate background swatch from the palette of media artwork.
+ *
+ * @param palette Artwork palette, should be obtained from {@link generateArtworkPaletteBuilder}
+ * @return Swatch that should be used as the background of the media notification.
+ */
+ private static Palette.Swatch findBackgroundSwatch(Palette palette) {
// by default we use the dominant palette
Palette.Swatch dominantSwatch = palette.getDominantSwatch();
if (dominantSwatch == null) {
- // We're not filtering on white or black
- mFilteredBackgroundHsl = null;
- return Color.WHITE;
+ return new Palette.Swatch(Color.WHITE, 100);
}
if (!isWhiteOrBlack(dominantSwatch.getHsl())) {
- mFilteredBackgroundHsl = dominantSwatch.getHsl();
- return dominantSwatch.getRgb();
+ return dominantSwatch;
}
// Oh well, we selected black or white. Lets look at the second color!
List<Palette.Swatch> swatches = palette.getSwatches();
@@ -270,38 +280,51 @@
}
}
if (second == null) {
- // We're not filtering on white or black
- mFilteredBackgroundHsl = null;
- return dominantSwatch.getRgb();
+ return dominantSwatch;
}
if (dominantSwatch.getPopulation() / highestNonWhitePopulation
> POPULATION_FRACTION_FOR_WHITE_OR_BLACK) {
// The dominant swatch is very dominant, lets take it!
// We're not filtering on white or black
- mFilteredBackgroundHsl = null;
- return dominantSwatch.getRgb();
+ return dominantSwatch;
} else {
- mFilteredBackgroundHsl = second.getHsl();
- return second.getRgb();
+ return second;
}
}
- private boolean isWhiteOrBlack(float[] hsl) {
- return isBlack(hsl) || isWhite(hsl);
+ /**
+ * Generate a palette builder for media artwork.
+ *
+ * For producing a smooth background transition, the palette is extracted from only the left
+ * side of the artwork.
+ *
+ * @param artwork Media artwork
+ * @return Builder that generates the {@link Palette} for the media artwork.
+ */
+ private static Palette.Builder generateArtworkPaletteBuilder(Bitmap artwork) {
+ // for the background we only take the left side of the image to ensure
+ // a smooth transition
+ return Palette.from(artwork)
+ .setRegion(0, 0, artwork.getWidth() / 2, artwork.getHeight())
+ .clearFilters() // we want all colors, red / white / black ones too!
+ .resizeBitmapArea(RESIZE_BITMAP_AREA);
}
+ private static boolean isWhiteOrBlack(float[] hsl) {
+ return isBlack(hsl) || isWhite(hsl);
+ }
/**
* @return true if the color represents a color which is close to black.
*/
- private boolean isBlack(float[] hslColor) {
+ private static boolean isBlack(float[] hslColor) {
return hslColor[2] <= BLACK_MAX_LIGHTNESS;
}
/**
* @return true if the color represents a color which is close to white.
*/
- private boolean isWhite(float[] hslColor) {
+ private static boolean isWhite(float[] hslColor) {
return hslColor[2] >= WHITE_MIN_LIGHTNESS;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
index 0a2e04f..b732966 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
@@ -97,7 +97,6 @@
HashMap<MessagingGroup, MessagingGroup> pairs = findPairs(ownGroups, otherGroups);
MessagingGroup lastPairedGroup = null;
float currentTranslation = 0;
- float transformationDistanceRemaining = 0;
for (int i = ownGroups.size() - 1; i >= 0; i--) {
MessagingGroup ownGroup = ownGroups.get(i);
MessagingGroup matchingGroup = pairs.get(ownGroup);
@@ -108,13 +107,10 @@
lastPairedGroup = ownGroup;
if (to){
float totalTranslation = ownGroup.getTop() - matchingGroup.getTop();
- transformationDistanceRemaining
- = matchingGroup.getAvatar().getTranslationY();
- currentTranslation = transformationDistanceRemaining - totalTranslation;
+ currentTranslation = matchingGroup.getAvatar().getTranslationY()
+ - totalTranslation;
} else {
- float totalTranslation = matchingGroup.getTop() - ownGroup.getTop();
currentTranslation = ownGroup.getAvatar().getTranslationY();
- transformationDistanceRemaining = currentTranslation - totalTranslation;
}
}
} else {
@@ -122,14 +118,20 @@
if (lastPairedGroup != null) {
adaptGroupAppear(ownGroup, transformationAmount, currentTranslation,
to);
- int distance = lastPairedGroup.getTop() - ownGroup.getTop();
- float transformationDistance = mTransformInfo.isAnimating()
- ? distance
- : ownGroup.getHeight() * 0.75f;
- float translationProgress = transformationDistanceRemaining
- - (distance - transformationDistance);
- groupTransformationAmount =
- translationProgress / transformationDistance;
+ float newPosition = ownGroup.getTop() + currentTranslation;
+
+ if (!mTransformInfo.isAnimating()) {
+ // We fade the group away as soon as 1/2 of it is translated away on top
+ float fadeStart = -ownGroup.getHeight() * 0.5f;
+ groupTransformationAmount = (newPosition - fadeStart)
+ / Math.abs(fadeStart);
+ } else {
+ float fadeStart = -ownGroup.getHeight() * 0.75f;
+ // We want to fade out as soon as the animation starts, let's add the
+ // complete top in addition
+ groupTransformationAmount = (newPosition - fadeStart)
+ / (Math.abs(fadeStart) + ownGroup.getTop());
+ }
groupTransformationAmount = Math.max(0.0f, Math.min(1.0f,
groupTransformationAmount));
if (to) {
@@ -175,7 +177,8 @@
relativeOffset *= 0.5f;
}
ownGroup.getMessageContainer().setTranslationY(relativeOffset);
- ownGroup.setTranslationY(overallTranslation * 0.85f);
+ ownGroup.getSenderView().setTranslationY(relativeOffset);
+ ownGroup.setTranslationY(overallTranslation * 0.9f);
}
private void disappear(MessagingGroup ownGroup, float transformationAmount) {
@@ -256,6 +259,9 @@
float distanceToTop = child.getTop() + child.getHeight() + previousTranslation;
transformationAmount = distanceToTop / child.getHeight();
transformationAmount = Math.max(0.0f, Math.min(1.0f, transformationAmount));
+ if (to) {
+ transformationAmount = 1.0f - transformationAmount;
+ }
}
transformView(transformationAmount, to, child, otherChild, false, /* sameAsAny */
useLinearTransformation);
@@ -400,6 +406,7 @@
setClippingDeactivated(ownGroup.getSenderView(), false);
ownGroup.setTranslationY(0);
ownGroup.getMessageContainer().setTranslationY(0);
+ ownGroup.getSenderView().setTranslationY(0);
}
ownGroup.setTransformingImages(false);
ownGroup.updateClipRect();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 7d224fb..3ac5768 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -15,6 +15,9 @@
*/
package com.android.systemui.statusbar.notification;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_ERROR;
+
import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
@@ -30,6 +33,7 @@
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.NotificationUpdateHandler;
import com.android.systemui.statusbar.notification.collection.NotificationData;
@@ -63,6 +67,13 @@
private static final String TAG = "NotificationEntryMgr";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ /**
+ * Used when a notification is removed and it doesn't have a reason that maps to one of the
+ * reasons defined in NotificationListenerService
+ * (e.g. {@link NotificationListenerService.REASON_CANCEL})
+ */
+ public static final int UNDEFINED_DISMISS_REASON = 0;
+
@VisibleForTesting
protected final HashMap<String, NotificationEntry> mPendingNotifications = new HashMap<>();
@@ -82,6 +93,7 @@
final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders
= new ArrayList<>();
private final List<NotificationEntryListener> mNotificationEntryListeners = new ArrayList<>();
+ private NotificationRemoveInterceptor mRemoveInterceptor;
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -115,6 +127,11 @@
mNotificationEntryListeners.add(listener);
}
+ /** Sets the {@link NotificationRemoveInterceptor}. */
+ public void setNotificationRemoveInterceptor(NotificationRemoveInterceptor interceptor) {
+ mRemoveInterceptor = interceptor;
+ }
+
/**
* Our dependencies can have cyclic references, so some need to be lazy
*/
@@ -146,7 +163,8 @@
/** Adds a {@link NotificationLifetimeExtender}. */
public void addNotificationLifetimeExtender(NotificationLifetimeExtender extender) {
mNotificationLifetimeExtenders.add(extender);
- extender.setCallback(key -> removeNotification(key, mLatestRankingMap));
+ extender.setCallback(key -> removeNotification(key, mLatestRankingMap,
+ UNDEFINED_DISMISS_REASON));
}
public NotificationData getNotificationData() {
@@ -158,10 +176,18 @@
updateNotifications();
}
- public void performRemoveNotification(StatusBarNotification n) {
+ /**
+ * Requests a notification to be removed.
+ *
+ * @param n the notification to remove.
+ * @param reason why it is being removed e.g. {@link NotificationListenerService#REASON_CANCEL},
+ * or 0 if unknown.
+ */
+ public void performRemoveNotification(StatusBarNotification n, int reason) {
final NotificationVisibility nv = obtainVisibility(n.getKey());
removeNotificationInternal(
- n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */);
+ n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */,
+ reason);
}
private NotificationVisibility obtainVisibility(String key) {
@@ -193,7 +219,8 @@
@Override
public void handleInflationException(StatusBarNotification n, Exception e) {
removeNotificationInternal(
- n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */);
+ n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */,
+ REASON_ERROR);
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onInflationError(n, e);
}
@@ -228,9 +255,10 @@
}
@Override
- public void removeNotification(String key, NotificationListenerService.RankingMap ranking) {
+ public void removeNotification(String key, NotificationListenerService.RankingMap ranking,
+ int reason) {
removeNotificationInternal(key, ranking, obtainVisibility(key), false /* forceRemove */,
- false /* removedByUser */);
+ false /* removedByUser */, reason);
}
private void removeNotificationInternal(
@@ -238,7 +266,15 @@
@Nullable NotificationListenerService.RankingMap ranking,
@Nullable NotificationVisibility visibility,
boolean forceRemove,
- boolean removedByUser) {
+ boolean removedByUser,
+ int reason) {
+
+ if (mRemoveInterceptor != null
+ && mRemoveInterceptor.onNotificationRemoveRequested(key, reason)) {
+ // Remove intercepted; skip
+ return;
+ }
+
final NotificationEntry entry = mNotificationData.get(key);
abortExistingInflation(key);
@@ -342,7 +378,8 @@
Dependency.get(LeakDetector.class).trackInstance(entry);
// Construct the expanded view.
- requireBinder().inflateViews(entry, () -> performRemoveNotification(notification));
+ requireBinder().inflateViews(entry, () -> performRemoveNotification(notification,
+ REASON_CANCEL));
abortExistingInflation(key);
@@ -383,7 +420,8 @@
listener.onPreEntryUpdated(entry);
}
- requireBinder().inflateViews(entry, () -> performRemoveNotification(notification));
+ requireBinder().inflateViews(entry, () -> performRemoveNotification(notification,
+ REASON_CANCEL));
updateNotifications();
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index 09eb8a1..1af47dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -18,6 +18,7 @@
import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Color;
import android.provider.Settings;
@@ -33,6 +34,9 @@
public class NotificationUtils {
private static final int[] sLocationBase = new int[2];
private static final int[] sLocationOffset = new int[2];
+
+ @Nullable private static Boolean sUseNewInterruptionModel = null;
+
public static boolean isGrayscale(ImageView v, ContrastColorUtil colorUtil) {
Object isGrayscale = v.getTag(R.id.icon_is_grayscale);
if (isGrayscale != null) {
@@ -72,9 +76,15 @@
return (int) (dimensionPixelSize * factor);
}
- /** Returns the value of the new interruption model setting. */
+ /**
+ * Returns the value of the new interruption model setting. This result is cached and cannot
+ * change except through reboots/process restarts.
+ */
public static boolean useNewInterruptionModel(Context context) {
- return Settings.Secure.getInt(context.getContentResolver(),
- NOTIFICATION_NEW_INTERRUPTION_MODEL, 1) != 0;
+ if (sUseNewInterruptionModel == null) {
+ sUseNewInterruptionModel = Settings.Secure.getInt(context.getContentResolver(),
+ NOTIFICATION_NEW_INTERRUPTION_MODEL, 1) != 0;
+ }
+ return sUseNewInterruptionModel;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index d89354b..a3e18ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -247,7 +247,7 @@
*/
public boolean showInShadeWhenBubble() {
// We always show it in the shade if non-clearable
- return !isClearable() || mShowInShadeWhenBubble;
+ return !isRowDismissed() && (!isClearable() || mShowInShadeWhenBubble);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index c4ecb82..94f7e65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -270,6 +270,8 @@
}
}
+ // TODO: This method has side effects, it is NOT just logging that a notification
+ // was cleared, it also actually removes the notification
private void logNotificationClear(String key, StatusBarNotification notification,
NotificationVisibility nv) {
final String pkg = notification.getPackageName();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index c34d567..4f562a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -19,7 +19,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
-import android.animation.TimeAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
@@ -36,7 +35,8 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -174,7 +174,7 @@
setClipChildren(false);
setClipToPadding(false);
updateColors();
- mFalsingManager = FalsingManager.getInstance(context);
+ mFalsingManager = FalsingManagerFactory.getInstance(context);
mAccessibilityManager = AccessibilityManager.getInstance(mContext);
mDoubleTapHelper = new DoubleTapHelper(this, (active) -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
new file mode 100644
index 0000000..a065f67
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.notification.row
+
+import android.app.Dialog
+import android.app.INotificationManager
+import android.app.NotificationChannel
+import android.app.NotificationChannel.DEFAULT_CHANNEL_ID
+import android.app.NotificationChannelGroup
+import android.app.NotificationManager.IMPORTANCE_NONE
+import android.content.Context
+import android.graphics.Color
+import android.graphics.PixelFormat
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.ColorDrawable
+import android.util.Log
+import android.view.Gravity
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
+import android.view.Window
+import android.view.WindowManager
+import android.widget.TextView
+import com.android.internal.annotations.VisibleForTesting
+
+import com.android.systemui.R
+
+import javax.inject.Inject
+import javax.inject.Singleton
+
+const val TAG = "ChannelDialogController"
+
+@Singleton
+class ChannelEditorDialogController @Inject constructor(
+ c: Context,
+ private val noMan: INotificationManager
+) {
+ val context: Context = c.applicationContext
+
+ lateinit var dialog: Dialog
+
+ private var appIcon: Drawable? = null
+ private var appUid: Int? = null
+ private var packageName: String? = null
+ private var appName: String? = null
+ private var onSettingsClickListener: NotificationInfo.OnSettingsClickListener? = null
+
+ // Channels handed to us from NotificationInfo
+ @VisibleForTesting
+ internal val providedChannels = mutableListOf<NotificationChannel>()
+
+ // Map from NotificationChannel to importance
+ private val edits = mutableMapOf<NotificationChannel, Int>()
+ var appNotificationsEnabled = true
+
+ // Keep a mapping of NotificationChannel.getGroup() to the actual group name for display
+ @VisibleForTesting
+ internal val groupNameLookup = hashMapOf<String, CharSequence>()
+ private val channelGroupList = mutableListOf<NotificationChannelGroup>()
+
+ fun prepareDialogForApp(
+ appName: String,
+ packageName: String,
+ uid: Int,
+ channels: Set<NotificationChannel>,
+ appIcon: Drawable,
+ onSettingsClickListener: NotificationInfo.OnSettingsClickListener
+ ) {
+ this.appName = appName
+ this.packageName = packageName
+ this.appUid = uid
+ this.appIcon = appIcon
+ this.appNotificationsEnabled = checkAreAppNotificationsOn()
+ this.onSettingsClickListener = onSettingsClickListener
+
+ channelGroupList.clear()
+ channelGroupList.addAll(fetchNotificationChannelGroups())
+ buildGroupNameLookup()
+ padToFourChannels(channels)
+ }
+
+ private fun buildGroupNameLookup() {
+ channelGroupList.forEach { group ->
+ if (group.id != null) {
+ groupNameLookup[group.id] = group.name
+ }
+ }
+ }
+
+ private fun padToFourChannels(channels: Set<NotificationChannel>) {
+ providedChannels.clear()
+ // First, add all of the given channels
+ providedChannels.addAll(channels.asSequence().take(4))
+
+ // Then pad to 4 if we haven't been given that many
+ providedChannels.addAll(getDisplayableChannels(channelGroupList.asSequence())
+ .filterNot { providedChannels.contains(it) }
+ .distinct()
+ .take(4 - providedChannels.size))
+
+ // If we only got one channel and it has the default miscellaneous tag, then we actually
+ // are looking at an app with a targetSdk <= O, and it doesn't make much sense to show the
+ // channel
+ if (providedChannels.size == 1 && DEFAULT_CHANNEL_ID == providedChannels[0].id) {
+ providedChannels.clear()
+ }
+ }
+
+ private fun getDisplayableChannels(
+ groupList: Sequence<NotificationChannelGroup>
+ ): Sequence<NotificationChannel> {
+
+ val channels = groupList
+ .flatMap { group ->
+ group.channels.asSequence().filterNot { channel ->
+ channel.isImportanceLockedByOEM
+ || channel.importance == IMPORTANCE_NONE
+ || channel.isImportanceLockedByCriticalDeviceFunction
+ }
+ }
+
+ // TODO: sort these by avgSentWeekly, but for now let's just do alphabetical (why not)
+ return channels.sortedWith(compareBy { it.name?.toString() ?: it.id })
+ }
+
+ fun show() {
+ initDialog()
+ dialog.show()
+ }
+
+ private fun done() {
+ resetState()
+ dialog.dismiss()
+ }
+
+ private fun resetState() {
+ appIcon = null
+ appUid = null
+ packageName = null
+ appName = null
+
+ edits.clear()
+ providedChannels.clear()
+ groupNameLookup.clear()
+ }
+
+ fun groupNameForId(groupId: String?): CharSequence {
+ return groupNameLookup[groupId] ?: ""
+ }
+
+ fun proposeEditForChannel(channel: NotificationChannel, edit: Int) {
+ if (channel.importance == edit) {
+ edits.remove(channel)
+ } else {
+ edits[channel] = edit
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private fun fetchNotificationChannelGroups(): List<NotificationChannelGroup> {
+ return try {
+ noMan.getNotificationChannelGroupsForPackage(packageName!!, appUid!!, false)
+ .list as? List<NotificationChannelGroup> ?: listOf()
+ } catch (e: Exception) {
+ Log.e(TAG, "Error fetching channel groups", e)
+ listOf()
+ }
+ }
+
+ private fun checkAreAppNotificationsOn(): Boolean {
+ return try {
+ noMan.areNotificationsEnabledForPackage(packageName!!, appUid!!)
+ } catch (e: Exception) {
+ Log.e(TAG, "Error calling NoMan", e)
+ false
+ }
+ }
+
+ private fun applyAppNotificationsOn(b: Boolean) {
+ try {
+ noMan.setNotificationsEnabledForPackage(packageName!!, appUid!!, b)
+ } catch (e: Exception) {
+ Log.e(TAG, "Error calling NoMan", e)
+ }
+ }
+
+ private fun setChannelImportance(channel: NotificationChannel, importance: Int) {
+ try {
+ channel.importance = importance
+ noMan.updateNotificationChannelForPackage(packageName!!, appUid!!, channel)
+ } catch (e: Exception) {
+ Log.e(TAG, "Unable to update notification importance", e)
+ }
+ }
+
+ @VisibleForTesting
+ fun apply() {
+ for ((channel, importance) in edits) {
+ if (channel.importance != importance) {
+ setChannelImportance(channel, importance)
+ }
+ }
+
+ if (appNotificationsEnabled != checkAreAppNotificationsOn()) {
+ applyAppNotificationsOn(appNotificationsEnabled)
+ }
+ }
+
+ private fun initDialog() {
+ dialog = Dialog(context)
+
+ dialog.window?.requestFeature(Window.FEATURE_NO_TITLE)
+ dialog.apply {
+ setContentView(R.layout.notif_half_shelf)
+ setCanceledOnTouchOutside(true)
+ findViewById<ChannelEditorListView>(R.id.half_shelf_container).apply {
+ controller = this@ChannelEditorDialogController
+ appIcon = this@ChannelEditorDialogController.appIcon
+ appName = this@ChannelEditorDialogController.appName
+ channels = providedChannels
+ }
+
+ findViewById<TextView>(R.id.done_button)?.setOnClickListener {
+ apply()
+ done()
+ }
+
+ findViewById<TextView>(R.id.see_more_button)?.setOnClickListener {
+ onSettingsClickListener?.onClick(it, null, appUid!!)
+ dismiss()
+ }
+
+ window?.apply {
+ setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+ addFlags(wmFlags)
+ setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL)
+ setWindowAnimations(com.android.internal.R.style.Animation_InputMethod)
+
+ attributes = attributes.apply {
+ format = PixelFormat.TRANSLUCENT
+ title = ChannelEditorDialogController::class.java.simpleName
+ gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
+ width = MATCH_PARENT
+ height = WRAP_CONTENT
+ }
+ }
+ }
+ }
+
+ private val wmFlags = (WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
+ or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
new file mode 100644
index 0000000..7fea30c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.notification.row
+
+import android.app.NotificationChannel
+import android.app.NotificationManager.IMPORTANCE_DEFAULT
+import android.app.NotificationManager.IMPORTANCE_NONE
+import android.app.NotificationManager.IMPORTANCE_UNSPECIFIED
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.text.TextUtils
+import android.transition.AutoTransition
+import android.transition.TransitionManager
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.Switch
+import android.widget.TextView
+
+import com.android.systemui.R
+
+/**
+ * Half-shelf for notification channel controls
+ */
+class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) {
+ lateinit var controller: ChannelEditorDialogController
+ var appIcon: Drawable? = null
+ var appName: String? = null
+ var channels = mutableListOf<NotificationChannel>()
+ set(newValue) {
+ field = newValue
+ updateRows()
+ }
+
+ // The first row is for the entire app
+ private lateinit var appControlRow: AppControlView
+
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+
+ appControlRow = findViewById(R.id.app_control)
+ }
+
+ private fun updateRows() {
+ val enabled = controller.appNotificationsEnabled
+
+ val transition = AutoTransition()
+ transition.duration = 200
+ TransitionManager.beginDelayedTransition(this, transition)
+
+ // Remove any rows
+ val n = childCount
+ for (i in n.downTo(0)) {
+ val child = getChildAt(i)
+ if (child is ChannelRow) {
+ removeView(child)
+ }
+ }
+
+ updateAppControlRow(enabled)
+
+ if (enabled) {
+ val inflater = LayoutInflater.from(context)
+ for (channel in channels) {
+ addChannelRow(channel, inflater)
+ }
+ }
+ }
+
+ private fun addChannelRow(channel: NotificationChannel, inflater: LayoutInflater) {
+ val row = inflater.inflate(R.layout.notif_half_shelf_row, null) as ChannelRow
+ row.controller = controller
+ row.channel = channel
+ addView(row)
+ }
+
+ private fun updateAppControlRow(enabled: Boolean) {
+ appControlRow.iconView.setImageDrawable(appIcon)
+ appControlRow.channelName.text = context.resources
+ .getString(R.string.notification_channel_dialog_title, appName)
+ appControlRow.switch.isChecked = enabled
+ appControlRow.switch.setOnCheckedChangeListener { _, b ->
+ controller.appNotificationsEnabled = b
+ updateRows()
+ }
+ }
+}
+
+class AppControlView(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) {
+ lateinit var iconView: ImageView
+ lateinit var channelName: TextView
+ lateinit var switch: Switch
+
+ override fun onFinishInflate() {
+ iconView = findViewById(R.id.icon)
+ channelName = findViewById(R.id.app_name)
+ switch = findViewById(R.id.toggle)
+ }
+}
+
+class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) {
+
+ lateinit var controller: ChannelEditorDialogController
+ private lateinit var iconView: ImageView
+ private lateinit var channelName: TextView
+ private lateinit var channelDescription: TextView
+ private lateinit var switch: Switch
+ var gentle = false
+
+ var channel: NotificationChannel? = null
+ set(newValue) {
+ field = newValue
+ updateImportance()
+ updateViews()
+ }
+
+ override fun onFinishInflate() {
+ iconView = findViewById(R.id.icon)
+ channelName = findViewById(R.id.channel_name)
+ channelDescription = findViewById(R.id.channel_description)
+ switch = findViewById(R.id.toggle)
+ switch.setOnCheckedChangeListener { _, b ->
+ channel?.let {
+ controller.proposeEditForChannel(it, if (b) it.importance else IMPORTANCE_NONE)
+ }
+ }
+ }
+
+ private fun updateViews() {
+ val nc = channel ?: return
+
+ iconView.setImageDrawable(
+ if (gentle)
+ context.getDrawable(R.drawable.ic_notification_gentle)
+ else context.getDrawable(R.drawable.ic_notification_interruptive))
+
+ channelName.text = nc.name ?: "(missing)"
+
+ nc.group?.let { groupId ->
+ channelDescription.text = controller.groupNameForId(groupId)
+ }
+
+ if (nc.group == null || TextUtils.isEmpty(channelDescription.text)) {
+ channelDescription.visibility = View.GONE
+ } else {
+ channelDescription.visibility = View.VISIBLE
+ }
+
+ switch.isChecked = nc.importance != IMPORTANCE_NONE
+ }
+
+ private fun updateImportance() {
+ val importance = channel?.importance ?: 0
+ gentle = importance != IMPORTANCE_UNSPECIFIED && importance < IMPORTANCE_DEFAULT
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 1ef29c1..d731ba6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -76,7 +76,8 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
@@ -769,7 +770,9 @@
public void setHeaderVisibleAmount(float headerVisibleAmount) {
if (mHeaderVisibleAmount != headerVisibleAmount) {
mHeaderVisibleAmount = headerVisibleAmount;
- mPrivateLayout.setHeaderVisibleAmount(headerVisibleAmount);
+ for (NotificationContentView l : mLayouts) {
+ l.setHeaderVisibleAmount(headerVisibleAmount);
+ }
if (mChildrenContainer != null) {
mChildrenContainer.setHeaderVisibleAmount(headerVisibleAmount);
}
@@ -1241,7 +1244,6 @@
}
mStatusBarNotification.clearPackageContext();
mNotificationInflater.clearCachesAndReInflate();
- onNotificationUpdated();
}
@Override
@@ -1646,7 +1648,7 @@
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
- mFalsingManager = FalsingManager.getInstance(context);
+ mFalsingManager = FalsingManagerFactory.getInstance(context);
mNotificationInflater = new NotificationContentInflater(this);
mMenuRow = new NotificationMenuRow(mContext);
mImageResolver = new NotificationInlineImageResolver(context,
@@ -2397,6 +2399,14 @@
* it's a summary notification).
*/
public int getNumUniqueChannels() {
+ return getUniqueChannels().size();
+ }
+
+ /**
+ * Returns the channels covered by the notification row (including its children if
+ * it's a summary notification).
+ */
+ public ArraySet<NotificationChannel> getUniqueChannels() {
ArraySet<NotificationChannel> channels = new ArraySet<>();
channels.add(mEntry.channel);
@@ -2416,7 +2426,8 @@
}
}
}
- return channels.size();
+
+ return channels;
}
public void updateChildrenHeaderAppearance() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index b81d814..ad745f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -542,6 +542,12 @@
}
@Override
+ public void onViewAdded(View child) {
+ super.onViewAdded(child);
+ child.setTag(R.id.row_tag_for_content_view, mContainingNotification);
+ }
+
+ @Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
updateVisibility();
@@ -1893,4 +1899,8 @@
}
pw.println();
}
+
+ public RemoteInputView getExpandedRemoteInput() {
+ return mExpandedRemoteInput;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index faa7898..f15d6b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -18,7 +18,6 @@
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import android.app.INotificationManager;
import android.app.NotificationChannel;
@@ -26,6 +25,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
+import android.os.Bundle;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
@@ -125,13 +125,18 @@
* Sends an intent to open the notification settings for a particular package and optional
* channel.
*/
+ public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
private void startAppNotificationSettingsActivity(String packageName, final int appUid,
final NotificationChannel channel, ExpandableNotificationRow row) {
final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
intent.putExtra(Settings.EXTRA_APP_UID, appUid);
+
if (channel != null) {
+ final Bundle args = new Bundle();
intent.putExtra(EXTRA_FRAGMENT_ARG_KEY, channel.getId());
+ args.putString(EXTRA_FRAGMENT_ARG_KEY, channel.getId());
+ intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
}
mNotificationActivityStarter.startNotificationGutsIntent(intent, appUid, row);
}
@@ -301,7 +306,7 @@
iNotificationManager,
packageName,
row.getEntry().channel,
- row.getNumUniqueChannels(),
+ row.getUniqueChannels(),
sbn,
mCheckSaveListener,
onSettingsClick,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index d49f168..942f566 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -63,6 +63,7 @@
import com.android.systemui.statusbar.notification.logging.NotificationCounters;
import java.util.List;
+import java.util.Set;
/**
* The guts of a notification revealed when performing a long press. This also houses the blocking
@@ -96,12 +97,14 @@
private INotificationManager mINotificationManager;
private PackageManager mPm;
private MetricsLogger mMetricsLogger;
+ private ChannelEditorDialogController mChannelEditorDialogController;
private String mPackageName;
private String mAppName;
private int mAppUid;
private String mDelegatePkg;
private int mNumUniqueChannelsInRow;
+ private Set<NotificationChannel> mUniqueChannelsInRow;
private NotificationChannel mSingleNotificationChannel;
private int mStartingChannelImportance;
private boolean mWasShownHighPriority;
@@ -126,6 +129,7 @@
private NotificationGuts mGutsContainer;
private Drawable mSelectedBackground;
private Drawable mUnselectedBackground;
+ private Drawable mPkgIcon;
/** Whether this view is being shown as part of the blocking helper. */
private boolean mIsForBlockingHelper;
@@ -233,7 +237,7 @@
final INotificationManager iNotificationManager,
final String pkg,
final NotificationChannel notificationChannel,
- final int numUniqueChannelsInRow,
+ final Set<NotificationChannel> uniqueChannelsInRow,
final StatusBarNotification sbn,
final CheckSaveListener checkSaveListener,
final OnSettingsClickListener onSettingsClick,
@@ -244,7 +248,7 @@
boolean wasShownHighPriority)
throws RemoteException {
bindNotification(pm, iNotificationManager, pkg, notificationChannel,
- numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
+ uniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
onAppSettingsClick, isDeviceProvisioned, isNonblockable,
false /* isBlockingHelper */,
importance, wasShownHighPriority);
@@ -255,7 +259,7 @@
INotificationManager iNotificationManager,
String pkg,
NotificationChannel notificationChannel,
- int numUniqueChannelsInRow,
+ Set<NotificationChannel> uniqueChannelsInRow,
StatusBarNotification sbn,
CheckSaveListener checkSaveListener,
OnSettingsClickListener onSettingsClick,
@@ -268,8 +272,10 @@
throws RemoteException {
mINotificationManager = iNotificationManager;
mMetricsLogger = Dependency.get(MetricsLogger.class);
+ mChannelEditorDialogController = Dependency.get(ChannelEditorDialogController.class);
mPackageName = pkg;
- mNumUniqueChannelsInRow = numUniqueChannelsInRow;
+ mUniqueChannelsInRow = uniqueChannelsInRow;
+ mNumUniqueChannelsInRow = uniqueChannelsInRow.size();
mSbn = sbn;
mPm = pm;
mAppSettingsClickListener = onAppSettingsClick;
@@ -355,7 +361,7 @@
}
View turnOffButton = findViewById(R.id.turn_off_notifications);
- turnOffButton.setOnClickListener(getSettingsOnClickListener());
+ turnOffButton.setOnClickListener(getTurnOffNotificationsClickListener());
turnOffButton.setVisibility(turnOffButton.hasOnClickListeners() && !mIsNonblockable
? VISIBLE : GONE);
@@ -379,7 +385,7 @@
private void bindHeader() {
// Package name
- Drawable pkgicon = null;
+ mPkgIcon = null;
ApplicationInfo info;
try {
info = mPm.getApplicationInfo(
@@ -390,13 +396,13 @@
| PackageManager.MATCH_DIRECT_BOOT_AWARE);
if (info != null) {
mAppName = String.valueOf(mPm.getApplicationLabel(info));
- pkgicon = mPm.getApplicationIcon(info);
+ mPkgIcon = mPm.getApplicationIcon(info);
}
} catch (PackageManager.NameNotFoundException e) {
// app is gone, just show package name and generic icon
- pkgicon = mPm.getDefaultActivityIcon();
+ mPkgIcon = mPm.getDefaultActivityIcon();
}
- ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
+ ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(mPkgIcon);
((TextView) findViewById(R.id.pkgname)).setText(mAppName);
// Delegate
@@ -437,6 +443,16 @@
return null;
}
+ private OnClickListener getTurnOffNotificationsClickListener() {
+ return ((View view) -> {
+ if (mChannelEditorDialogController != null) {
+ mChannelEditorDialogController.prepareDialogForApp(mAppName, mPackageName, mAppUid,
+ mUniqueChannelsInRow, mPkgIcon, mOnSettingsClickListener);
+ mChannelEditorDialogController.show();
+ }
+ });
+ }
+
private void bindChannelDetails() throws RemoteException {
bindName();
bindGroup();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 1be2afe7..0b3871d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -17,8 +17,6 @@
package com.android.systemui.statusbar.notification.row.wrapper;
import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
-import static com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
- .DEFAULT_HEADER_VISIBLE_AMOUNT;
import android.app.Notification;
import android.content.Context;
@@ -53,19 +51,17 @@
= new PathInterpolator(0.4f, 0f, 0.7f, 1f);
protected final ViewTransformationHelper mTransformationHelper;
- private final int mTranslationForHeader;
protected int mColor;
private ImageView mIcon;
private NotificationExpandButton mExpandButton;
- private NotificationHeaderView mNotificationHeader;
+ protected NotificationHeaderView mNotificationHeader;
private TextView mHeaderText;
private ImageView mWorkProfileImage;
private boolean mIsLowPriority;
private boolean mTransformLowPriorityTitle;
private boolean mShowExpandButtonAtEnd;
- protected float mHeaderTranslation;
protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
super(ctx, view, row);
@@ -101,10 +97,6 @@
}, TRANSFORMING_VIEW_TITLE);
resolveHeaderViews();
addAppOpsOnClickListener(row);
- mTranslationForHeader = ctx.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin)
- - ctx.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin_top);
}
protected void resolveHeaderViews() {
@@ -130,9 +122,6 @@
// Reinspect the notification.
resolveHeaderViews();
- if (row.getHeaderVisibleAmount() != DEFAULT_HEADER_VISIBLE_AMOUNT) {
- setHeaderVisibleAmount(row.getHeaderVisibleAmount());
- }
updateTransformedTypes();
addRemainingTransformTypes();
updateCropToPaddingForImageViews();
@@ -199,19 +188,6 @@
}
@Override
- public void setHeaderVisibleAmount(float headerVisibleAmount) {
- super.setHeaderVisibleAmount(headerVisibleAmount);
- mNotificationHeader.setAlpha(headerVisibleAmount);
- mHeaderTranslation = (1.0f - headerVisibleAmount) * mTranslationForHeader;
- mView.setTranslationY(mHeaderTranslation);
- }
-
- @Override
- public int getHeaderTranslation() {
- return (int) mHeaderTranslation;
- }
-
- @Override
public NotificationHeaderView getNotificationHeader() {
return mNotificationHeader;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index b54de5a..91c43a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -200,32 +200,40 @@
private boolean canSeekMedia() {
if (mMediaController == null || mMediaController.getPlaybackState() == null) {
+ Log.d(TAG, "Cannot seek media because the controller is invalid");
return false;
}
long actions = mMediaController.getPlaybackState().getActions();
- return (actions == 0 || (actions & PlaybackState.ACTION_SEEK_TO) != 0);
+ Log.d(TAG, "Playback state actions are " + actions);
+ return ((actions & PlaybackState.ACTION_SEEK_TO) != 0);
}
protected final Runnable mUpdatePlaybackUi = new Runnable() {
@Override
public void run() {
- if (mMediaController != null && mMediaController.getMetadata() != null
- && mSeekBar != null) {
- long position = mMediaController.getPlaybackState().getPosition();
- long duration = mMediaController.getMetadata().getLong(
- MediaMetadata.METADATA_KEY_DURATION);
+ if (mMediaController != null && mSeekBar != null) {
+ MediaMetadata metadata = mMediaController.getMetadata();
+ PlaybackState playbackState = mMediaController.getPlaybackState();
- if (mDuration != duration) {
- mDuration = duration;
- mSeekBar.setMax((int) mDuration);
- mSeekBarTotalTime.setText(millisecondsToTimeString(duration));
+ if (metadata != null && playbackState != null) {
+ long position = playbackState.getPosition();
+ long duration = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
+
+ if (mDuration != duration) {
+ mDuration = duration;
+ mSeekBar.setMax((int) mDuration);
+ mSeekBarTotalTime.setText(millisecondsToTimeString(duration));
+ }
+ mSeekBar.setProgress((int) position);
+
+ mSeekBarElapsedTime.setText(millisecondsToTimeString(position));
+ } else {
+ Log.d(TAG, "Controller missing data " + metadata + " " + playbackState);
+ clearTimer();
}
- mSeekBar.setProgress((int) position);
-
- mSeekBarElapsedTime.setText(millisecondsToTimeString(position));
} else {
- // We no longer have a media session / notification
+ Log.d(TAG, "No longer have a valid media controller");
clearTimer();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index ff5e15b..7ebdb93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.row.wrapper;
+import static com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.DEFAULT_HEADER_VISIBLE_AMOUNT;
+
import android.app.PendingIntent;
import android.content.Context;
import android.content.res.ColorStateList;
@@ -49,6 +51,7 @@
*/
public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapper {
+ private final int mTranslationForHeader;
protected ImageView mPicture;
private ProgressBar mProgressBar;
private TextView mTitle;
@@ -63,6 +66,7 @@
private ArraySet<PendingIntent> mCancelledPendingIntents = new ArraySet<>();
private UiOffloadThread mUiOffloadThread;
private View mRemoteInputHistory;
+ private float mHeaderTranslation;
protected NotificationTemplateViewWrapper(Context ctx, View view,
ExpandableNotificationRow row) {
@@ -131,6 +135,10 @@
}
}, TRANSFORMING_VIEW_TEXT);
+ mTranslationForHeader = ctx.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_content_margin)
+ - ctx.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_content_margin_top);
}
private void resolveTemplateViews(StatusBarNotification notification) {
@@ -280,6 +288,9 @@
// the transformation types and we need to have our values set by then.
resolveTemplateViews(row.getStatusBarNotification());
super.onContentUpdated(row);
+ if (row.getHeaderVisibleAmount() != DEFAULT_HEADER_VISIBLE_AMOUNT) {
+ setHeaderVisibleAmount(row.getHeaderVisibleAmount());
+ }
}
@Override
@@ -334,6 +345,19 @@
}
@Override
+ public int getHeaderTranslation() {
+ return (int) mHeaderTranslation;
+ }
+
+ @Override
+ public void setHeaderVisibleAmount(float headerVisibleAmount) {
+ super.setHeaderVisibleAmount(headerVisibleAmount);
+ mNotificationHeader.setAlpha(headerVisibleAmount);
+ mHeaderTranslation = (1.0f - headerVisibleAmount) * mTranslationForHeader;
+ mView.setTranslationY(mHeaderTranslation);
+ }
+
+ @Override
public int getExtraMeasureHeight() {
int extra = 0;
if (mActions != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index ce92280..8c6d101 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.stack;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.util.MathUtils;
@@ -30,18 +31,18 @@
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider;
import java.util.ArrayList;
-import java.util.List;
/**
* A global state to track all input states for the algorithm.
*/
public class AmbientState {
- private static final int NO_SECTION_BOUNDARY = -1;
private static final float MAX_PULSE_HEIGHT = 100000f;
+ private final SectionProvider mSectionProvider;
private ArrayList<ExpandableView> mDraggedViews = new ArrayList<>();
private int mScrollY;
private int mAnchorViewIndex;
@@ -51,7 +52,6 @@
private float mOverScrollTopAmount;
private float mOverScrollBottomAmount;
private int mSpeedBumpIndex = -1;
- private final List<Integer> mSectionBoundaryIndices = new ArrayList<>();
private boolean mDark;
private boolean mHideSensitive;
private AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
@@ -84,8 +84,10 @@
private float mPulseHeight = MAX_PULSE_HEIGHT;
private float mDozeAmount = 0.0f;
- public AmbientState(Context context) {
- mSectionBoundaryIndices.add(NO_SECTION_BOUNDARY);
+ public AmbientState(
+ Context context,
+ @NonNull SectionProvider sectionProvider) {
+ mSectionProvider = sectionProvider;
reload(context);
}
@@ -245,25 +247,8 @@
mSpeedBumpIndex = shelfIndex;
}
- /**
- * Returns the index of the boundary between two sections, where the first section is at index
- * {@code boundaryNum}.
- */
- public int getSectionBoundaryIndex(int boundaryNum) {
- return mSectionBoundaryIndices.get(boundaryNum);
- }
-
- /** Returns true if the item at {@code index} is directly below a section boundary. */
- public boolean beginsNewSection(int index) {
- return mSectionBoundaryIndices.contains(index);
- }
-
- /**
- * Sets the index of the boundary between the section at {@code boundaryNum} and the following
- * section to {@code boundaryIndex}.
- */
- public void setSectionBoundaryIndex(int boundaryNum, int boundaryIndex) {
- mSectionBoundaryIndices.set(boundaryNum, boundaryIndex);
+ public SectionProvider getSectionProvider() {
+ return mSectionProvider;
}
public float getStackTranslation() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
new file mode 100644
index 0000000..82599f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.notification.stack;
+
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+/**
+ * Manages the boundaries of the two notification sections (high priority and low priority). Also
+ * shows/hides the headers for those sections where appropriate.
+ *
+ * TODO: Move remaining sections logic from NSSL into this class.
+ */
+class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvider {
+ private final NotificationStackScrollLayout mParent;
+ private final ActivityStarter mActivityStarter;
+ private final boolean mUseMultipleSections;
+
+ private SectionHeaderView mGentleHeader;
+ private boolean mGentleHeaderVisible = false;
+ @Nullable private View.OnClickListener mOnClearGentleNotifsClickListener;
+
+ NotificationSectionsManager(
+ NotificationStackScrollLayout parent,
+ ActivityStarter activityStarter,
+ boolean useMultipleSections) {
+ mParent = parent;
+ mActivityStarter = activityStarter;
+ mUseMultipleSections = useMultipleSections;
+ }
+
+ /**
+ * Must be called before use. Should be called again whenever inflation-related things change,
+ * such as density or theme changes.
+ */
+ void inflateViews(Context context) {
+ int oldPos = -1;
+ if (mGentleHeader != null) {
+ if (mGentleHeader.getTransientContainer() != null) {
+ mGentleHeader.getTransientContainer().removeView(mGentleHeader);
+ } else if (mGentleHeader.getParent() != null) {
+ oldPos = mParent.indexOfChild(mGentleHeader);
+ mParent.removeView(mGentleHeader);
+ }
+ }
+
+ mGentleHeader = (SectionHeaderView) LayoutInflater.from(context).inflate(
+ R.layout.status_bar_notification_section_header, mParent, false);
+ mGentleHeader.setOnHeaderClickListener(this::onGentleHeaderClick);
+ mGentleHeader.setOnClearAllClickListener(this::onClearGentleNotifsClick);
+
+ if (oldPos != -1) {
+ mParent.addView(mGentleHeader, oldPos);
+ }
+ }
+
+ /** Listener for when the "clear all" buttton is clciked on the gentle notification header. */
+ void setOnClearGentleNotifsClickListener(View.OnClickListener listener) {
+ mOnClearGentleNotifsClickListener = listener;
+ }
+
+ /** Must be called whenever the UI mode changes (i.e. when we enter night mode). */
+ void onUiModeChanged() {
+ mGentleHeader.onUiModeChanged();
+ }
+
+ @Override
+ public boolean beginsSection(View view) {
+ return view == mGentleHeader;
+ }
+
+ /**
+ * Should be called whenever notifs are added, removed, or updated. Updates section boundary
+ * bookkeeping and adds/moves/removes section headers if appropriate.
+ */
+ void updateSectionBoundaries() {
+ if (!mUseMultipleSections) {
+ return;
+ }
+
+ int firstGentleNotifIndex = -1;
+
+ final int n = mParent.getChildCount();
+ for (int i = 0; i < n; i++) {
+ View child = mParent.getChildAt(i);
+ if (child instanceof ExpandableNotificationRow
+ && child.getVisibility() != View.GONE) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ if (!row.getEntry().isHighPriority()) {
+ firstGentleNotifIndex = i;
+ break;
+ }
+ }
+ }
+
+ adjustGentleHeaderVisibilityAndPosition(firstGentleNotifIndex);
+
+ mGentleHeader.setAreThereDismissableGentleNotifs(
+ mParent.hasActiveClearableNotifications(ROWS_GENTLE));
+ }
+
+ private void adjustGentleHeaderVisibilityAndPosition(int firstGentleNotifIndex) {
+ final int currentHeaderIndex = mParent.indexOfChild(mGentleHeader);
+
+ if (firstGentleNotifIndex == -1) {
+ if (mGentleHeaderVisible) {
+ mGentleHeaderVisible = false;
+ mParent.removeView(mGentleHeader);
+ }
+ } else {
+ if (!mGentleHeaderVisible) {
+ mGentleHeaderVisible = true;
+ // If the header is animating away, it will still have a parent, so detach it first
+ // TODO: We should really cancel the active animations here. This will happen
+ // automatically when the view's intro animation starts, but it's a fragile link.
+ if (mGentleHeader.getTransientContainer() != null) {
+ mGentleHeader.getTransientContainer().removeTransientView(mGentleHeader);
+ mGentleHeader.setTransientContainer(null);
+ }
+ mParent.addView(mGentleHeader, firstGentleNotifIndex);
+ } else if (currentHeaderIndex != firstGentleNotifIndex - 1) {
+ // Relocate the header to be immediately before the first child in the section
+ int targetIndex = firstGentleNotifIndex;
+ if (currentHeaderIndex < firstGentleNotifIndex) {
+ // Adjust the target index to account for the header itself being temporarily
+ // removed during the position change.
+ targetIndex--;
+ }
+
+ mParent.changeViewPosition(mGentleHeader, targetIndex);
+ }
+ }
+ }
+
+ /**
+ * Updates the boundaries (as tracked by their first and last views) of the high and low
+ * priority sections.
+ *
+ * @return {@code true} If the last view in the top section changed (so we need to animate).
+ */
+ boolean updateFirstAndLastViewsInSections(
+ final NotificationSection highPrioritySection,
+ final NotificationSection lowPrioritySection,
+ ActivatableNotificationView firstChild,
+ ActivatableNotificationView lastChild) {
+ if (mUseMultipleSections) {
+ ActivatableNotificationView previousLastHighPriorityChild =
+ highPrioritySection.getLastVisibleChild();
+ ActivatableNotificationView previousFirstLowPriorityChild =
+ lowPrioritySection.getFirstVisibleChild();
+ ActivatableNotificationView lastHighPriorityChild = getLastHighPriorityChild();
+ ActivatableNotificationView firstLowPriorityChild = getFirstLowPriorityChild();
+ if (lastHighPriorityChild != null && firstLowPriorityChild != null) {
+ highPrioritySection.setFirstVisibleChild(firstChild);
+ highPrioritySection.setLastVisibleChild(lastHighPriorityChild);
+ lowPrioritySection.setFirstVisibleChild(firstLowPriorityChild);
+ lowPrioritySection.setLastVisibleChild(lastChild);
+ } else if (lastHighPriorityChild != null) {
+ highPrioritySection.setFirstVisibleChild(firstChild);
+ highPrioritySection.setLastVisibleChild(lastChild);
+ lowPrioritySection.setFirstVisibleChild(null);
+ lowPrioritySection.setLastVisibleChild(null);
+ } else {
+ highPrioritySection.setFirstVisibleChild(null);
+ highPrioritySection.setLastVisibleChild(null);
+ lowPrioritySection.setFirstVisibleChild(firstChild);
+ lowPrioritySection.setLastVisibleChild(lastChild);
+ }
+ return lastHighPriorityChild != previousLastHighPriorityChild
+ || firstLowPriorityChild != previousFirstLowPriorityChild;
+ } else {
+ highPrioritySection.setFirstVisibleChild(firstChild);
+ highPrioritySection.setLastVisibleChild(lastChild);
+ return false;
+ }
+ }
+
+ @VisibleForTesting
+ SectionHeaderView getGentleHeaderView() {
+ return mGentleHeader;
+ }
+
+ @Nullable
+ private ActivatableNotificationView getFirstLowPriorityChild() {
+ return mGentleHeaderVisible ? mGentleHeader : null;
+ }
+
+ @Nullable
+ private ActivatableNotificationView getLastHighPriorityChild() {
+ ActivatableNotificationView lastChildBeforeGap = null;
+ int childCount = mParent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = mParent.getChildAt(i);
+ if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ if (!row.getEntry().isHighPriority()) {
+ break;
+ } else {
+ lastChildBeforeGap = row;
+ }
+ }
+ }
+ return lastChildBeforeGap;
+ }
+
+ private void onGentleHeaderClick(View v) {
+ Intent intent = new Intent(Settings.ACTION_NOTIFICATION_SETTINGS);
+ mActivityStarter.startActivity(
+ intent,
+ true,
+ true,
+ Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ }
+
+ private void onClearGentleNotifsClick(View v) {
+ if (mOnClearGentleNotifsClickListener != null) {
+ mOnClearGentleNotifsClickListener.onClick(v);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 7a9da6b..de187f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -23,10 +23,13 @@
import static com.android.systemui.statusbar.phone.NotificationIconAreaController.LOW_PRIORITY;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeAnimator;
import android.animation.ValueAnimator;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WallpaperManager;
@@ -46,6 +49,7 @@
import android.os.Bundle;
import android.os.ServiceManager;
import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -83,8 +87,10 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
@@ -140,6 +146,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -496,6 +503,7 @@
private final NotificationGutsManager
mNotificationGutsManager = Dependency.get(NotificationGutsManager.class);
+ private final NotificationSectionsManager mSectionsManager;
/**
* If the {@link NotificationShelf} should be visible when dark.
*/
@@ -509,7 +517,8 @@
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
NotificationRoundnessManager notificationRoundnessManager,
AmbientPulseManager ambientPulseManager,
- DynamicPrivacyController dynamicPrivacyController) {
+ DynamicPrivacyController dynamicPrivacyController,
+ ActivityStarter activityStarter) {
super(context, attrs, 0, 0);
Resources res = getResources();
@@ -520,7 +529,20 @@
}
mAmbientPulseManager = ambientPulseManager;
- mAmbientState = new AmbientState(context);
+
+ mSectionsManager =
+ new NotificationSectionsManager(
+ this,
+ activityStarter,
+ NotificationUtils.useNewInterruptionModel(context));
+ mSectionsManager.inflateViews(context);
+ mSectionsManager.setOnClearGentleNotifsClickListener(v -> {
+ // Leave the shade open if there will be other notifs left over to clear
+ final boolean closeShade = !hasActiveClearableNotifications(ROWS_HIGH_PRIORITY);
+ clearNotifications(ROWS_GENTLE, closeShade);
+ });
+
+ mAmbientState = new AmbientState(context, mSectionsManager);
mRoundnessManager = notificationRoundnessManager;
mBgColor = context.getColor(R.color.notification_shade_background_color);
int minHeight = res.getDimensionPixelSize(R.dimen.notification_min_height);
@@ -533,7 +555,7 @@
getContext(), mMenuEventListener);
mStackScrollAlgorithm = createStackScrollAlgorithm(context);
initView(context);
- mFalsingManager = FalsingManager.getInstance(context);
+ mFalsingManager = FalsingManagerFactory.getInstance(context);
mShouldDrawNotificationBackground =
res.getBoolean(R.bool.config_drawNotificationBackground);
mFadeNotificationsOnDismiss =
@@ -627,6 +649,7 @@
inflateFooterView();
inflateEmptyShadeView();
updateFooter();
+ mSectionsManager.inflateViews(mContext);
}
@Override
@@ -660,7 +683,7 @@
@VisibleForTesting
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void updateFooter() {
- boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications();
+ boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications(ROWS_ALL);
boolean showFooterView = (showDismissView ||
mEntryManager.getNotificationData().getActiveNotifications().size() != 0)
&& mStatusBarState != StatusBarState.KEYGUARD
@@ -673,14 +696,15 @@
* Return whether there are any clearable notifications
*/
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public boolean hasActiveClearableNotifications() {
+ public boolean hasActiveClearableNotifications(@SelectedRows int selection) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (!(child instanceof ExpandableNotificationRow)) {
continue;
}
- if (((ExpandableNotificationRow) child).canViewBeDismissed()) {
+ final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ if (row.canViewBeDismissed() && matchesSelection(row, selection)) {
return true;
}
}
@@ -737,6 +761,7 @@
mBgColor = mContext.getColor(R.color.notification_shade_background_color);
updateBackgroundDimming();
mShelf.onUiModeChanged();
+ mSectionsManager.onUiModeChanged();
}
@ShadeViewRefactor(RefactorComponent.DECORATOR)
@@ -1682,11 +1707,6 @@
return mScrollingEnabled;
}
- @ShadeViewRefactor(RefactorComponent.ADAPTER)
- private boolean canChildBeDismissed(View v) {
- return StackScrollAlgorithm.canChildBeDismissed(v);
- }
-
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
private boolean onKeyguard() {
return mStatusBarState == StatusBarState.KEYGUARD;
@@ -2578,41 +2598,6 @@
return null;
}
- @ShadeViewRefactor(RefactorComponent.COORDINATOR)
- @Nullable
- private ActivatableNotificationView getLastHighPriorityChild() {
- ActivatableNotificationView lastChildBeforeGap = null;
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- if (!row.getEntry().isHighPriority()) {
- break;
- } else {
- lastChildBeforeGap = row;
- }
- }
- }
- return lastChildBeforeGap;
- }
-
- @ShadeViewRefactor(RefactorComponent.COORDINATOR)
- @Nullable
- private ActivatableNotificationView getFirstLowPriorityChild() {
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- if (!row.getEntry().isHighPriority()) {
- return row;
- }
- }
- }
- return null;
- }
-
/**
* Fling the scroll view
*
@@ -3178,7 +3163,7 @@
ActivatableNotificationView firstChild = getFirstChildWithBackground();
ActivatableNotificationView lastChild = getLastChildWithBackground();
- boolean sectionViewsChanged = updateFirstAndLastViewsInSectionsByPriority(
+ boolean sectionViewsChanged = mSectionsManager.updateFirstAndLastViewsInSections(
mSections[0], mSections[1], firstChild, lastChild);
if (mAnimationsEnabled && mIsExpanded) {
@@ -3196,44 +3181,6 @@
invalidate();
}
- /** @return {@code true} if the last view in the top section changed (so we need to animate). */
- private boolean updateFirstAndLastViewsInSectionsByPriority(
- final NotificationSection highPrioritySection,
- final NotificationSection lowPrioritySection,
- ActivatableNotificationView firstChild,
- ActivatableNotificationView lastChild) {
- if (NotificationUtils.useNewInterruptionModel(mContext)) {
- ActivatableNotificationView previousLastHighPriorityChild =
- highPrioritySection.getLastVisibleChild();
- ActivatableNotificationView previousFirstLowPriorityChild =
- lowPrioritySection.getFirstVisibleChild();
- ActivatableNotificationView lastHighPriorityChild = getLastHighPriorityChild();
- ActivatableNotificationView firstLowPriorityChild = getFirstLowPriorityChild();
- if (lastHighPriorityChild != null && firstLowPriorityChild != null) {
- highPrioritySection.setFirstVisibleChild(firstChild);
- highPrioritySection.setLastVisibleChild(lastHighPriorityChild);
- lowPrioritySection.setFirstVisibleChild(firstLowPriorityChild);
- lowPrioritySection.setLastVisibleChild(lastChild);
- } else if (lastHighPriorityChild != null) {
- highPrioritySection.setFirstVisibleChild(firstChild);
- highPrioritySection.setLastVisibleChild(lastChild);
- lowPrioritySection.setFirstVisibleChild(null);
- lowPrioritySection.setLastVisibleChild(null);
- } else {
- highPrioritySection.setFirstVisibleChild(null);
- highPrioritySection.setLastVisibleChild(null);
- lowPrioritySection.setFirstVisibleChild(firstChild);
- lowPrioritySection.setLastVisibleChild(lastChild);
- }
- return lastHighPriorityChild != previousLastHighPriorityChild
- || firstLowPriorityChild != previousFirstLowPriorityChild;
- } else {
- highPrioritySection.setFirstVisibleChild(firstChild);
- highPrioritySection.setLastVisibleChild(lastChild);
- return false;
- }
- }
-
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private void onViewAddedInternal(ExpandableView child) {
updateHideSensitiveForChild(child);
@@ -4593,11 +4540,6 @@
return mAmbientState.isDimmed();
}
- @VisibleForTesting
- int getSectionBoundaryIndex(int boundaryNum) {
- return mAmbientState.getSectionBoundaryIndex(boundaryNum);
- }
-
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
private void setDimAmount(float dimAmount) {
mDimAmount = dimAmount;
@@ -4982,7 +4924,7 @@
} else {
child.setMinClipTopAmount(0);
}
- previousChildWillBeDismissed = canChildBeDismissed(child);
+ previousChildWillBeDismissed = StackScrollAlgorithm.canChildBeDismissed(child);
}
}
@@ -5538,7 +5480,9 @@
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void clearAllNotifications() {
+ private void clearNotifications(
+ @SelectedRows int selection,
+ boolean closeShade) {
// animate-swipe all dismissable notifications, then animate the shade closed
int numChildren = getChildCount();
@@ -5550,7 +5494,7 @@
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
boolean parentVisible = false;
boolean hasClipBounds = child.getClipBounds(mTmpRect);
- if (canChildBeDismissed(child)) {
+ if (includeChildInDismissAll(row, selection)) {
viewsToRemove.add(row);
if (child.getVisibility() == View.VISIBLE
&& (!hasClipBounds || mTmpRect.height() > 0)) {
@@ -5564,50 +5508,94 @@
List<ExpandableNotificationRow> children = row.getNotificationChildren();
if (children != null) {
for (ExpandableNotificationRow childRow : children) {
- viewsToRemove.add(childRow);
- if (parentVisible && row.areChildrenExpanded()
- && canChildBeDismissed(childRow)) {
- hasClipBounds = childRow.getClipBounds(mTmpRect);
- if (childRow.getVisibility() == View.VISIBLE
- && (!hasClipBounds || mTmpRect.height() > 0)) {
- viewsToHide.add(childRow);
+ if (includeChildInDismissAll(row, selection)) {
+ viewsToRemove.add(childRow);
+ if (parentVisible && row.areChildrenExpanded()) {
+ hasClipBounds = childRow.getClipBounds(mTmpRect);
+ if (childRow.getVisibility() == View.VISIBLE
+ && (!hasClipBounds || mTmpRect.height() > 0)) {
+ viewsToHide.add(childRow);
+ }
}
}
}
}
}
}
+
if (viewsToRemove.isEmpty()) {
- mStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
+ if (closeShade) {
+ mStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
+ }
return;
}
- mShadeController.addPostCollapseAction(() -> {
- setDismissAllInProgress(false);
+ performDismissAllAnimations(viewsToHide, closeShade, () -> {
for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
- if (canChildBeDismissed(rowToRemove)) {
- mEntryManager.removeNotification(rowToRemove.getEntry().key, null);
+ if (StackScrollAlgorithm.canChildBeDismissed(rowToRemove)) {
+ if (selection == ROWS_ALL) {
+ // TODO: This is a listener method; we shouldn't be calling it. Can we just
+ // call performRemoveNotification as below?
+ mEntryManager.removeNotification(
+ rowToRemove.getEntry().key,
+ null /* ranking */,
+ NotificationListenerService.REASON_CANCEL_ALL);
+ } else {
+ mEntryManager.performRemoveNotification(
+ rowToRemove.getEntry().notification,
+ NotificationListenerService.REASON_CANCEL_ALL);
+ }
} else {
rowToRemove.resetTranslation();
}
}
- try {
- mBarService.onClearAllNotifications(mLockscreenUserManager.getCurrentUserId());
- } catch (Exception ex) {
+ if (selection == ROWS_ALL) {
+ try {
+ mBarService.onClearAllNotifications(mLockscreenUserManager.getCurrentUserId());
+ } catch (Exception ex) {
+ }
}
});
-
- performDismissAllAnimations(viewsToHide);
}
+ private boolean includeChildInDismissAll(
+ ExpandableNotificationRow row,
+ @SelectedRows int selection) {
+ return StackScrollAlgorithm.canChildBeDismissed(row) && matchesSelection(row, selection);
+ }
+
+ /**
+ * Given a list of rows, animates them away in a staggered fashion as if they were dismissed.
+ * Doesn't actually dismiss them, though -- that must be done in the onAnimationComplete
+ * handler.
+ *
+ * @param hideAnimatedList List of rows to animated away. Should only be views that are
+ * currently visible, or else the stagger will look funky.
+ * @param closeShade Whether to close the shade after the stagger animation completes.
+ * @param onAnimationComplete Called after the entire animation completes (including the shade
+ * closing if appropriate). The rows must be dismissed for real here.
+ */
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void performDismissAllAnimations(ArrayList<View> hideAnimatedList) {
- Runnable animationFinishAction = () -> {
- mStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
+ private void performDismissAllAnimations(
+ final ArrayList<View> hideAnimatedList,
+ final boolean closeShade,
+ final Runnable onAnimationComplete) {
+
+ final Runnable onSlideAwayAnimationComplete = () -> {
+ if (closeShade) {
+ mShadeController.addPostCollapseAction(() -> {
+ setDismissAllInProgress(false);
+ onAnimationComplete.run();
+ });
+ mStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
+ } else {
+ setDismissAllInProgress(false);
+ onAnimationComplete.run();
+ }
};
if (hideAnimatedList.isEmpty()) {
- animationFinishAction.run();
+ onSlideAwayAnimationComplete.run();
return;
}
@@ -5624,7 +5612,7 @@
View view = hideAnimatedList.get(i);
Runnable endRunnable = null;
if (i == 0) {
- endRunnable = animationFinishAction;
+ endRunnable = onSlideAwayAnimationComplete;
}
dismissViewAnimated(view, endRunnable, totalDelay, ANIMATION_DURATION_SWIPE);
currentDelay = Math.max(50, currentDelay - rowDelayDecrement);
@@ -5639,7 +5627,7 @@
R.layout.status_bar_notification_footer, this, false);
footerView.setDismissButtonClickListener(v -> {
mMetricsLogger.action(MetricsEvent.ACTION_DISMISS_ALL_NOTES);
- clearAllNotifications();
+ clearNotifications(ROWS_ALL, true /* closeShade */);
});
footerView.setManageButtonClickListener(this::manageNotifications);
setFooterView(footerView);
@@ -5810,27 +5798,7 @@
/** Updates the indices of the boundaries between sections. */
@ShadeViewRefactor(RefactorComponent.INPUT)
public void updateSectionBoundaries() {
- int gapIndex = -1;
- if (NotificationUtils.useNewInterruptionModel(mContext)) {
- int currentIndex = 0;
- final int n = getChildCount();
- for (int i = 0; i < n; i++) {
- View view = getChildAt(i);
- if (view.getVisibility() == View.GONE
- || !(view instanceof ExpandableNotificationRow)) {
- continue;
- }
- ExpandableNotificationRow row = (ExpandableNotificationRow) view;
- if (!row.getEntry().isHighPriority()) {
- if (currentIndex > 0) {
- gapIndex = currentIndex;
- }
- break;
- }
- currentIndex++;
- }
- }
- mAmbientState.setSectionBoundaryIndex(0, gapIndex);
+ mSectionsManager.updateSectionBoundaries();
}
private void updateContinuousBackgroundDrawing() {
@@ -5866,6 +5834,21 @@
mSwipeHelper.resetExposedMenuView(animate, force);
}
+ private static boolean matchesSelection(
+ ExpandableNotificationRow row,
+ @SelectedRows int selection) {
+ switch (selection) {
+ case ROWS_ALL:
+ return true;
+ case ROWS_HIGH_PRIORITY:
+ return row.getEntry().isHighPriority();
+ case ROWS_GENTLE:
+ return !row.getEntry().isHighPriority();
+ default:
+ throw new IllegalArgumentException("Unknown selection: " + selection);
+ }
+ }
+
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
static class AnimationEvent {
@@ -6350,7 +6333,7 @@
@Override
public boolean canChildBeDismissed(View v) {
- return NotificationStackScrollLayout.this.canChildBeDismissed(v);
+ return StackScrollAlgorithm.canChildBeDismissed(v);
}
@Override
@@ -6557,4 +6540,15 @@
public ExpandHelper.Callback getExpandHelperCallback() {
return mExpandHelperCallback;
}
+
+ /** Enum for selecting some or all notification rows (does not included non-notif views). */
+ @Retention(SOURCE)
+ @IntDef({ROWS_ALL, ROWS_HIGH_PRIORITY, ROWS_GENTLE})
+ public @interface SelectedRows {}
+ /** All rows representing notifs. */
+ public static final int ROWS_ALL = 0;
+ /** Only rows where entry.isHighPriority() is true. */
+ public static final int ROWS_HIGH_PRIORITY = 1;
+ /** Only rows where entry.isHighPriority() is false. */
+ public static final int ROWS_GENTLE = 2;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
new file mode 100644
index 0000000..e2f702d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.notification.stack;
+
+import android.content.Context;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+
+/**
+ * Similar in size and appearance to the NotificationShelf, appears at the beginning of some
+ * notification sections. Currently only used for gentle notifications.
+ */
+public class SectionHeaderView extends ActivatableNotificationView {
+ private View mContents;
+ private TextView mLabelView;
+ private ImageView mClearAllButton;
+
+ private final RectF mTmpRect = new RectF();
+
+ public SectionHeaderView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mContents = findViewById(R.id.content);
+ mLabelView = findViewById(R.id.header_label);
+ mClearAllButton = findViewById(R.id.btn_clear_all);
+ }
+
+ @Override
+ protected View getContentView() {
+ return mContents;
+ }
+
+ /** Must be called whenever the UI mode changes (i.e. when we enter night mode). */
+ void onUiModeChanged() {
+ updateBackgroundColors();
+ mLabelView.setTextColor(
+ getContext().getColor(R.color.notification_section_header_label_color));
+ mClearAllButton.setImageResource(
+ R.drawable.status_bar_notification_section_header_clear_btn);
+ }
+
+ void setAreThereDismissableGentleNotifs(boolean areThereDismissableGentleNotifs) {
+ mClearAllButton.setVisibility(areThereDismissableGentleNotifs ? View.VISIBLE : View.GONE);
+ }
+
+ @Override
+ protected boolean disallowSingleClick(MotionEvent event) {
+ // Disallow single click on lockscreen if user is tapping on clear all button
+ mTmpRect.set(
+ mClearAllButton.getLeft(),
+ mClearAllButton.getTop(),
+ mClearAllButton.getLeft() + mClearAllButton.getWidth(),
+ mClearAllButton.getTop() + mClearAllButton.getHeight());
+ return mTmpRect.contains(event.getX(), event.getY());
+ }
+
+ /**
+ * Fired whenever the user clicks on the body of the header (e.g. no sub-buttons or anything).
+ */
+ void setOnHeaderClickListener(View.OnClickListener listener) {
+ mContents.setOnClickListener(listener);
+ }
+
+ /** Fired when the user clicks on the "X" button on the far right of the header. */
+ void setOnClearAllClickListener(View.OnClickListener listener) {
+ mClearAllButton.setOnClickListener(listener);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index f97a7e6..60061c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -58,7 +58,9 @@
private float mHeadsUpInset;
private int mPinnedZTranslationExtra;
- public StackScrollAlgorithm(Context context, ViewGroup hostView) {
+ public StackScrollAlgorithm(
+ Context context,
+ ViewGroup hostView) {
mHostView = hostView;
initView(context);
}
@@ -364,22 +366,15 @@
*/
private void updatePositionsForState(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
-
if (ANCHOR_SCROLLING) {
float currentYPosition = algorithmState.anchorViewY;
int childCount = algorithmState.visibleChildren.size();
for (int i = algorithmState.anchorViewIndex; i < childCount; i++) {
- if (i > algorithmState.anchorViewIndex && ambientState.beginsNewSection(i)) {
- currentYPosition += mGapHeight;
- }
currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
false /* reverse */);
}
currentYPosition = algorithmState.anchorViewY;
for (int i = algorithmState.anchorViewIndex - 1; i >= 0; i--) {
- if (ambientState.beginsNewSection(i + 1)) {
- currentYPosition -= mGapHeight;
- }
currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
true /* reverse */);
}
@@ -388,9 +383,6 @@
float currentYPosition = -algorithmState.scrollY;
int childCount = algorithmState.visibleChildren.size();
for (int i = 0; i < childCount; i++) {
- if (ambientState.beginsNewSection(i)) {
- currentYPosition += mGapHeight;
- }
currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
false /* reverse */);
}
@@ -421,8 +413,15 @@
float currentYPosition,
boolean reverse) {
ExpandableView child = algorithmState.visibleChildren.get(i);
+ final boolean applyGapHeight =
+ childNeedsGapHeight(ambientState.getSectionProvider(), algorithmState, i, child);
ExpandableViewState childViewState = child.getViewState();
childViewState.location = ExpandableViewState.LOCATION_UNKNOWN;
+
+ if (applyGapHeight && !reverse) {
+ currentYPosition += mGapHeight;
+ }
+
int paddingAfterChild = getPaddingAfterChild(algorithmState, child);
int childHeight = getMaxAllowedChildHeight(child);
if (reverse) {
@@ -459,6 +458,9 @@
if (reverse) {
currentYPosition = childViewState.yTranslation;
+ if (applyGapHeight) {
+ currentYPosition -= mGapHeight;
+ }
} else {
currentYPosition = childViewState.yTranslation + childHeight + paddingAfterChild;
if (currentYPosition <= 0) {
@@ -473,6 +475,18 @@
return currentYPosition;
}
+ private boolean childNeedsGapHeight(
+ SectionProvider sectionProvider,
+ StackScrollAlgorithmState algorithmState,
+ int visibleIndex,
+ View child) {
+ boolean needsGapHeight = sectionProvider.beginsSection(child) && visibleIndex > 0;
+ if (ANCHOR_SCROLLING) {
+ needsGapHeight &= visibleIndex != algorithmState.anchorViewIndex;
+ }
+ return needsGapHeight;
+ }
+
protected int getPaddingAfterChild(StackScrollAlgorithmState algorithmState,
ExpandableView child) {
return algorithmState.getPaddingAfterChild(child);
@@ -727,4 +741,15 @@
}
}
+ /**
+ * Interface for telling the SSA when a new notification section begins (so it can add in
+ * appropriate margins).
+ */
+ public interface SectionProvider {
+ /**
+ * True if this view starts a new "section" of notifications, such as the gentle
+ * notifications section. False if sections are not enabled.
+ */
+ boolean beginsSection(View view);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 6a93c7c..539bc7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -23,7 +23,6 @@
import android.view.View;
import android.view.View.AccessibilityDelegate;
-import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonInterface.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonInterface.java
new file mode 100644
index 0000000..150a960
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonInterface.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 The Android Open 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 android.graphics.drawable.Drawable;
+
+public interface ButtonInterface {
+
+ void setImageDrawable(@Nullable Drawable drawable);
+
+ void abortCurrentGesture();
+
+ void setVertical(boolean vertical);
+
+ void setDarkIntensity(float intensity);
+
+ void setDelayTouchFeedback(boolean shouldDelay);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index cd0a43e..4691a31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -27,7 +27,8 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.KeyguardAffordanceView;
@@ -101,7 +102,7 @@
mHintGrowAmount =
mContext.getResources().getDimensionPixelSize(R.dimen.hint_grow_amount_sideways);
mFlingAnimationUtils = new FlingAnimationUtils(mContext, 0.4f);
- mFalsingManager = FalsingManager.getInstance(mContext);
+ mFalsingManager = FalsingManagerFactory.getInstance(mContext);
}
private void initIcons() {
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 3c2881d..bbae62e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -43,8 +43,8 @@
import com.android.keyguard.R;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
-import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.plugins.FalsingManager;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 1b86693..bc2d00f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -117,8 +117,13 @@
public void loadDimens(Resources res) {
mClockNotificationsMargin = res.getDimensionPixelSize(
R.dimen.keyguard_clock_notifications_margin);
- mContainerTopPadding = res.getDimensionPixelSize(
- R.dimen.keyguard_clock_top_margin);
+ // Consider the lock icon when determining the minimum top padding between the status bar
+ // and top of the clock.
+ mContainerTopPadding = Math.max(res.getDimensionPixelSize(
+ R.dimen.keyguard_clock_top_margin),
+ res.getDimensionPixelSize(R.dimen.keyguard_lock_height)
+ + res.getDimensionPixelSize(R.dimen.keyguard_lock_padding)
+ + res.getDimensionPixelSize(R.dimen.keyguard_clock_lock_margin));
mBurnInPreventionOffsetX = res.getDimensionPixelSize(
R.dimen.burn_in_prevention_offset_x);
mBurnInPreventionOffsetY = res.getDimensionPixelSize(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index a831a5d..f93c5f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import android.content.Context;
@@ -27,6 +28,8 @@
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricSourceType;
+import android.os.Handler;
+import android.os.Trace;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -34,6 +37,7 @@
import androidx.annotation.Nullable;
import com.android.internal.graphics.ColorUtils;
+import com.android.internal.telephony.IccCardConstants;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
@@ -66,12 +70,14 @@
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final AccessibilityController mAccessibilityController;
private final DockManager mDockManager;
+ private final Handler mMainHandler;
private int mLastState = 0;
private boolean mTransientBiometricsError;
private boolean mScreenOn;
private boolean mLastScreenOn;
private boolean mIsFaceUnlockState;
+ private boolean mSimLocked;
private int mDensity;
private boolean mPulsing;
private boolean mDozing;
@@ -82,6 +88,9 @@
private boolean mLastBouncerVisible;
private int mIconColor;
private float mDozeAmount;
+ private int mIconRes;
+ private boolean mWasPulsingOnThisFrame;
+ private boolean mWakeAndUnlockRunning;
private final Runnable mDrawOffTimeout = () -> update(true /* forceUpdate */);
private final DockManager.DockEventListener mDockEventListener =
@@ -112,6 +121,14 @@
}
@Override
+ public void onSimStateChanged(int subId, int slotId,
+ IccCardConstants.State simState) {
+ boolean oldSimLocked = mSimLocked;
+ mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure();
+ update(oldSimLocked != mSimLocked);
+ }
+
+ @Override
public void onKeyguardVisibilityChanged(boolean showing) {
update();
}
@@ -133,7 +150,8 @@
StatusBarStateController statusBarStateController,
ConfigurationController configurationController,
AccessibilityController accessibilityController,
- @Nullable DockManager dockManager) {
+ @Nullable DockManager dockManager,
+ @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
super(context, attrs);
mContext = context;
mUnlockMethodCache = UnlockMethodCache.getInstance(context);
@@ -142,6 +160,7 @@
mConfigurationController = configurationController;
mStatusBarStateController = statusBarStateController;
mDockManager = dockManager;
+ mMainHandler = mainHandler;
}
@Override
@@ -151,6 +170,7 @@
mConfigurationController.addCallback(this);
mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
mUnlockMethodCache.addListener(this);
+ mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure();
if (mDockManager != null) {
mDockManager.addListener(mDockEventListener);
}
@@ -214,39 +234,39 @@
mPulsing, mLastDozing, mDozing, mBouncerVisible);
boolean isAnim = iconAnimRes != -1;
- Drawable icon;
- if (isAnim) {
- // Load the animation resource.
- icon = mContext.getDrawable(iconAnimRes);
- } else {
- // Load the static icon resource based on the current state.
- icon = getIconForState(state);
- }
+ int iconRes = isAnim ? iconAnimRes : getIconForState(state);
+ if (iconRes != mIconRes) {
+ mIconRes = iconRes;
- final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
- ? (AnimatedVectorDrawable) icon
- : null;
- setImageDrawable(icon, false);
- updateDarkTint();
- if (mIsFaceUnlockState) {
- announceForAccessibility(getContext().getString(
- R.string.accessibility_scanning_face));
- }
+ Drawable icon = mContext.getDrawable(iconRes);
+ final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
+ ? (AnimatedVectorDrawable) icon
+ : null;
+ setImageDrawable(icon, false);
+ if (mIsFaceUnlockState) {
+ announceForAccessibility(getContext().getString(
+ R.string.accessibility_scanning_face));
+ }
- if (animation != null && isAnim) {
- animation.forceAnimationOnUI();
- animation.clearAnimationCallbacks();
- animation.registerAnimationCallback(new Animatable2.AnimationCallback() {
- @Override
- public void onAnimationEnd(Drawable drawable) {
- if (getDrawable() == animation && state == getState()
- && doesAnimationLoop(iconAnimRes)) {
- animation.start();
+ if (animation != null && isAnim) {
+ animation.forceAnimationOnUI();
+ animation.clearAnimationCallbacks();
+ animation.registerAnimationCallback(new Animatable2.AnimationCallback() {
+ @Override
+ public void onAnimationEnd(Drawable drawable) {
+ if (getDrawable() == animation && state == getState()
+ && doesAnimationLoop(iconAnimRes)) {
+ animation.start();
+ } else {
+ Trace.endAsyncSection("LockIcon#Animation", state);
+ }
}
- }
- });
- animation.start();
+ });
+ Trace.beginAsyncSection("LockIcon#Animation", state);
+ animation.start();
+ }
}
+ updateDarkTint();
if (isAnim && !mLastScreenOn) {
removeCallbacks(mDrawOffTimeout);
@@ -262,7 +282,8 @@
mLastBouncerVisible = mBouncerVisible;
}
- boolean invisible = mDozing && (!mPulsing || mDocked);
+ boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked);
+ boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning;
setVisibility(invisible ? INVISIBLE : VISIBLE);
updateClickability();
}
@@ -300,7 +321,7 @@
}
}
- private Drawable getIconForState(int state) {
+ private int getIconForState(int state) {
int iconRes;
switch (state) {
case STATE_LOCKED:
@@ -318,25 +339,27 @@
throw new IllegalArgumentException();
}
- return mContext.getDrawable(iconRes);
+ return iconRes;
}
private boolean doesAnimationLoop(int resourceId) {
return resourceId == com.android.internal.R.anim.lock_scanning;
}
- private static int getAnimationResForTransition(int oldState, int newState,
+ private int getAnimationResForTransition(int oldState, int newState,
boolean wasPulsing, boolean pulsing, boolean wasDozing, boolean dozing,
boolean bouncerVisible) {
// Never animate when screen is off
- if (dozing && !pulsing) {
+ if (dozing && !pulsing && !mWasPulsingOnThisFrame) {
return -1;
}
boolean isError = oldState != STATE_BIOMETRICS_ERROR && newState == STATE_BIOMETRICS_ERROR;
boolean justUnlocked = oldState != STATE_LOCK_OPEN && newState == STATE_LOCK_OPEN;
boolean justLocked = oldState == STATE_LOCK_OPEN && newState == STATE_LOCKED;
+ boolean nowPulsing = !wasPulsing && pulsing;
+ boolean turningOn = wasDozing && !dozing && !mWasPulsingOnThisFrame;
if (isError) {
return com.android.internal.R.anim.lock_to_error;
@@ -346,7 +369,7 @@
return com.android.internal.R.anim.lock_lock;
} else if (newState == STATE_SCANNING_FACE && bouncerVisible) {
return com.android.internal.R.anim.lock_scanning;
- } else if (!wasPulsing && pulsing && newState != STATE_LOCK_OPEN) {
+ } else if ((nowPulsing || turningOn) && newState != STATE_LOCK_OPEN) {
return com.android.internal.R.anim.lock_in;
}
return -1;
@@ -356,7 +379,7 @@
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
if (mTransientBiometricsError) {
return STATE_BIOMETRICS_ERROR;
- } else if (mUnlockMethodCache.canSkipBouncer()) {
+ } else if (mUnlockMethodCache.canSkipBouncer() && !mSimLocked) {
return STATE_LOCK_OPEN;
} else if (updateMonitor.isFaceDetectionRunning()) {
return STATE_SCANNING_FACE;
@@ -377,6 +400,12 @@
*/
public void setPulsing(boolean pulsing) {
mPulsing = pulsing;
+ if (!mPulsing) {
+ mWasPulsingOnThisFrame = true;
+ mMainHandler.post(() -> {
+ mWasPulsingOnThisFrame = false;
+ });
+ }
update();
}
@@ -427,4 +456,23 @@
public void onUnlockMethodStateChanged() {
update();
}
+
+ /**
+ * We need to hide the lock whenever there's a fingerprint unlock, otherwise you'll see the
+ * icon on top of the black front scrim.
+ */
+ public void onBiometricAuthModeChanged(boolean wakeAndUnlock) {
+ if (wakeAndUnlock) {
+ mWakeAndUnlockRunning = true;
+ }
+ update();
+ }
+
+ /**
+ * Triggered after the unlock animation is over and the user is looking at launcher.
+ */
+ public void onKeyguardFadedAway() {
+ mWakeAndUnlockRunning = false;
+ update();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 38eed16..1429718 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -449,13 +449,6 @@
}
@Override
- public void topAppWindowChanged(int displayId, boolean showMenu) {
- if (displayId == mDisplayId && mNavigationBarView != null) {
- mNavigationBarView.setMenuVisibility(showMenu);
- }
- }
-
- @Override
public void setWindowState(
int displayId, @WindowType int window, @WindowVisibleState int state) {
if (displayId == mDisplayId
@@ -716,7 +709,6 @@
if (shouldDisableNavbarGestures()) {
return false;
}
- mNavigationBarView.onNavigationButtonLongPress(v);
mMetricsLogger.action(MetricsEvent.ACTION_ASSIST_LONG_PRESS);
Bundle args = new Bundle();
args.putInt(
@@ -756,12 +748,10 @@
}
private boolean onLongPressBackHome(View v) {
- mNavigationBarView.onNavigationButtonLongPress(v);
return onLongPressNavigationButtons(v, R.id.back, R.id.home);
}
private boolean onLongPressBackRecents(View v) {
- mNavigationBarView.onNavigationButtonLongPress(v);
return onLongPressNavigationButtons(v, R.id.back, R.id.recent_apps);
}
@@ -988,6 +978,7 @@
@Override
public void onNavigationModeChanged(int mode) {
mNavBarMode = mode;
+ updateScreenPinningGestures();
}
public void disableAnimationsDuringHide(long delay) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 963fc54..a12ae96 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -35,23 +35,15 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider;
import com.android.systemui.recents.OverviewProxyService;
-import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.phone.ReverseLinearLayout.ReverseRelativeLayout;
import com.android.systemui.statusbar.policy.KeyButtonView;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.tuner.TunerService.Tunable;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Objects;
public class NavigationBarInflaterView extends FrameLayout
- implements Tunable, PluginListener<NavBarButtonProvider>,
- NavigationModeController.ModeChangedListener {
+ implements NavigationModeController.ModeChangedListener {
private static final String TAG = "NavBarInflater";
@@ -84,8 +76,8 @@
public static final String KEY_CODE_END = ")";
private static final String WEIGHT_SUFFIX = "W";
private static final String WEIGHT_CENTERED_SUFFIX = "WC";
-
- private final List<NavBarButtonProvider> mPlugins = new ArrayList<>();
+ private static final String ABSOLUTE_SUFFIX = "A";
+ private static final String ABSOLUTE_VERTICAL_CENTERED_SUFFIX = "C";
protected LayoutInflater mLayoutInflater;
protected LayoutInflater mLandscapeInflater;
@@ -158,32 +150,11 @@
}
@Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- Dependency.get(TunerService.class).addTunable(this, NAV_BAR_VIEWS, NAV_BAR_LEFT,
- NAV_BAR_RIGHT);
- Dependency.get(PluginManager.class).addPluginListener(this,
- NavBarButtonProvider.class, true /* Allow multiple */);
- }
-
- @Override
protected void onDetachedFromWindow() {
- Dependency.get(TunerService.class).removeTunable(this);
- Dependency.get(PluginManager.class).removePluginListener(this);
Dependency.get(NavigationModeController.class).removeListener(this);
super.onDetachedFromWindow();
}
- @Override
- public void onTuningChanged(String key, String newValue) {
- if (NAV_BAR_VIEWS.equals(key)) {
- setNavigationBarLayout(newValue);
- } else if (NAV_BAR_LEFT.equals(key) || NAV_BAR_RIGHT.equals(key)) {
- clearViews();
- inflateLayout(mCurrentLayout);
- }
- }
-
public void setNavigationBarLayout(String layoutValue) {
if (!Objects.equals(mCurrentLayout, layoutValue)) {
mUsingCustomLayout = layoutValue != null;
@@ -353,17 +324,20 @@
String sizeStr = extractSize(buttonSpec);
if (sizeStr == null) return v;
- if (sizeStr.contains(WEIGHT_SUFFIX)) {
+ if (sizeStr.contains(WEIGHT_SUFFIX) || sizeStr.contains(ABSOLUTE_SUFFIX)) {
// To support gravity, wrap in RelativeLayout and apply gravity to it.
// Children wanting to use gravity must be smaller then the frame.
- float weight = Float.parseFloat(sizeStr.substring(0, sizeStr.indexOf(WEIGHT_SUFFIX)));
ReverseRelativeLayout frame = new ReverseRelativeLayout(mContext);
LayoutParams childParams = new LayoutParams(v.getLayoutParams());
// Compute gravity to apply
int gravity = (landscape) ? (start ? Gravity.TOP : Gravity.BOTTOM)
: (start ? Gravity.START : Gravity.END);
- if (sizeStr.endsWith(WEIGHT_CENTERED_SUFFIX)) gravity = Gravity.CENTER;
+ if (sizeStr.endsWith(WEIGHT_CENTERED_SUFFIX)) {
+ gravity = Gravity.CENTER;
+ } else if (sizeStr.endsWith(ABSOLUTE_VERTICAL_CENTERED_SUFFIX)) {
+ gravity = Gravity.CENTER_VERTICAL;
+ }
// Set default gravity, flipped if needed in reversed layouts (270 RTL and 90 LTR)
frame.setDefaultGravity(gravity);
@@ -371,8 +345,16 @@
frame.addView(v, childParams);
- // Use weighting to set the width of the frame
- frame.setLayoutParams(new LinearLayout.LayoutParams(0, MATCH_PARENT, weight));
+ if (sizeStr.contains(WEIGHT_SUFFIX)) {
+ // Use weighting to set the width of the frame
+ float weight = Float.parseFloat(
+ sizeStr.substring(0, sizeStr.indexOf(WEIGHT_SUFFIX)));
+ frame.setLayoutParams(new LinearLayout.LayoutParams(0, MATCH_PARENT, weight));
+ } else {
+ int width = (int) convertDpToPx(mContext,
+ Float.parseFloat(sizeStr.substring(0, sizeStr.indexOf(ABSOLUTE_SUFFIX))));
+ frame.setLayoutParams(new LinearLayout.LayoutParams(width, MATCH_PARENT));
+ }
// Ensure ripples can be drawn outside bounds
frame.setClipChildren(false);
@@ -391,16 +373,9 @@
View v = null;
String button = extractButton(buttonSpec);
if (LEFT.equals(button)) {
- String s = Dependency.get(TunerService.class).getValue(NAV_BAR_LEFT, NAVSPACE);
- button = extractButton(s);
+ button = extractButton(NAVSPACE);
} else if (RIGHT.equals(button)) {
- String s = Dependency.get(TunerService.class).getValue(NAV_BAR_RIGHT, MENU_IME_ROTATE);
- button = extractButton(s);
- }
- // Let plugins go first so they can override a standard view if they want.
- for (NavBarButtonProvider provider : mPlugins) {
- v = provider.createView(buttonSpec, parent);
- if (v != null) return v;
+ button = extractButton(MENU_IME_ROTATE);
}
if (HOME.equals(button)) {
v = inflater.inflate(R.layout.home, parent, false);
@@ -490,8 +465,6 @@
}
}
-
-
private void clearViews() {
if (mButtonDispatchers != null) {
for (int i = 0; i < mButtonDispatchers.size(); i++) {
@@ -508,17 +481,7 @@
}
}
- @Override
- public void onPluginConnected(NavBarButtonProvider plugin, Context context) {
- mPlugins.add(plugin);
- clearViews();
- inflateLayout(mCurrentLayout);
- }
-
- @Override
- public void onPluginDisconnected(NavBarButtonProvider plugin) {
- mPlugins.remove(plugin);
- clearViews();
- inflateLayout(mCurrentLayout);
+ private static float convertDpToPx(Context context, float dp) {
+ return dp * context.getResources().getDisplayMetrics().density;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 4e4a6aec..9e0aff0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -174,7 +174,6 @@
if (mAutoDim) {
applyLightsOut(false, true);
}
- mView.onDarkIntensityChange(darkIntensity);
}
@Override
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 1c03844..d85b8ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
@@ -38,10 +37,8 @@
import android.graphics.Region;
import android.graphics.Region.Op;
import android.os.Bundle;
-import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.MotionEvent;
@@ -52,7 +49,6 @@
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
import android.view.WindowInsets;
import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.inputmethod.InputMethodManager;
@@ -65,13 +61,9 @@
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.AssistManager;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.statusbar.phone.NavGesture;
-import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsOnboarding;
-import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -82,7 +74,7 @@
import java.io.PrintWriter;
import java.util.function.Consumer;
-public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture>,
+public class NavigationBarView extends FrameLayout implements
NavigationModeController.ModeChangedListener {
final static boolean DEBUG = false;
final static String TAG = "StatusBar/NavBarView";
@@ -118,7 +110,6 @@
private KeyButtonDrawable mDockedIcon;
private final EdgeBackGestureHandler mEdgeBackGestureHandler;
- private GestureHelper mGestureHelper;
private final DeadZone mDeadZone;
private boolean mDeadZoneConsuming = false;
private final NavigationBarTransitions mBarTransitions;
@@ -268,8 +259,6 @@
// Set up the context group of buttons
mContextualButtonGroup = new ContextualButtonGroup(R.id.menu_container);
- final ContextualButton menuButton = new ContextualButton(R.id.menu,
- R.drawable.ic_sysbar_menu);
final ContextualButton imeSwitcherButton = new ContextualButton(R.id.ime_switcher,
R.drawable.ic_ime_switcher_default);
final RotationContextButton rotateSuggestionButton = new RotationContextButton(
@@ -278,7 +267,6 @@
final ContextualButton accessibilityButton =
new ContextualButton(R.id.accessibility_button,
R.drawable.ic_sysbar_accessibility_button);
- mContextualButtonGroup.addButton(menuButton);
mContextualButtonGroup.addButton(imeSwitcherButton);
if (!isGesturalMode) {
mContextualButtonGroup.addButton(rotateSuggestionButton);
@@ -306,7 +294,6 @@
mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
mButtonDispatchers.put(R.id.home_handle, new ButtonDispatcher(R.id.home_handle));
mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
- mButtonDispatchers.put(R.id.menu, menuButton);
mButtonDispatchers.put(R.id.ime_switcher, imeSwitcherButton);
mButtonDispatchers.put(R.id.accessibility_button, accessibilityButton);
mButtonDispatchers.put(R.id.rotate_suggestion, rotateSuggestionButton);
@@ -353,9 +340,6 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
shouldDeadZoneConsumeTouchEvents(event);
- if (mGestureHelper != null && mGestureHelper.onTouchEvent(event)) {
- return true;
- }
return super.onTouchEvent(event);
}
@@ -406,10 +390,6 @@
return mButtonDispatchers.get(R.id.recent_apps);
}
- public ButtonDispatcher getMenuButton() {
- return mButtonDispatchers.get(R.id.menu);
- }
-
public ButtonDispatcher getBackButton() {
return mButtonDispatchers.get(R.id.back);
}
@@ -636,6 +616,8 @@
// as they are used for exiting.
final boolean pinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
if (mOverviewProxyService.isEnabled()) {
+ // Force disable recents when not in legacy mode
+ disableRecent |= !QuickStepContract.isLegacyMode(mNavBarMode);
if (pinningActive) {
disableBack = disableHome = false;
}
@@ -716,16 +698,10 @@
}
}
- public void onNavigationButtonLongPress(View v) {
- if (mGestureHelper != null) {
- mGestureHelper.onNavigationButtonLongPress(v);
- }
- }
-
- public void onPanelExpandedChange(boolean expanded) {
+ public void onPanelExpandedChange() {
updateSlippery();
mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
- expanded, getContext().getDisplayId());
+ mPanelView.isFullyExpanded(), getContext().getDisplayId());
}
public void updateStates() {
@@ -795,10 +771,6 @@
}
}
- public void setMenuVisibility(final boolean show) {
- mContextualButtonGroup.setButtonVisibility(R.id.menu, show);
- }
-
public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
mLongClickableAccessibilityButton = longClickable;
getAccessibilityButton().setLongClickable(longClickable);
@@ -821,17 +793,8 @@
reloadNavIcons();
}
- public void onDarkIntensityChange(float intensity) {
- if (mGestureHelper != null) {
- mGestureHelper.onDarkIntensityChange(intensity);
- }
- }
-
@Override
protected void onDraw(Canvas canvas) {
- if (mGestureHelper != null) {
- mGestureHelper.onDraw(canvas);
- }
mDeadZone.onDraw(canvas);
super.onDraw(canvas);
}
@@ -847,9 +810,6 @@
updateButtonLocation(getRotateSuggestionButton(), mRotationButtonBounds, true);
// TODO: Handle button visibility changes
mOverviewProxyService.onActiveNavBarRegionChanges(mActiveRegion);
- if (mGestureHelper != null) {
- mGestureHelper.onLayout(changed, left, top, right, bottom);
- }
mRecentsOnboarding.setNavBarHeight(getMeasuredHeight());
}
@@ -948,25 +908,11 @@
if (!isLayoutDirectionResolved()) {
resolveLayoutDirection();
}
- updateTaskSwitchHelper();
updateNavButtonIcons();
getHomeButton().setVertical(mIsVertical);
}
- private void updateTaskSwitchHelper() {
- if (mGestureHelper == null) return;
- boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
- int navBarPos = NAV_BAR_INVALID;
- try {
- navBarPos = WindowManagerGlobal.getWindowManagerService().getNavBarPosition(
- getContext().getDisplayId());
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to get nav bar position.", e);
- }
- mGestureHelper.setBarState(isRtl, navBarPos);
- }
-
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int w = MeasureSpec.getSize(widthMeasureSpec);
@@ -1013,7 +959,6 @@
mTmpLastConfiguration.updateFrom(mConfiguration);
mConfiguration.updateFrom(newConfig);
boolean uiCarModeChanged = updateCarMode();
- updateTaskSwitchHelper();
updateIcons(mTmpLastConfiguration);
updateRecentsIcon();
mRecentsOnboarding.onConfigurationChanged(mConfiguration);
@@ -1082,9 +1027,6 @@
super.onAttachedToWindow();
requestApplyInsets();
reorient();
- onPluginDisconnected(null); // Create default gesture helper
- Dependency.get(PluginManager.class).addPluginListener(this,
- NavGesture.class, false /* Only one */);
onNavigationModeChanged(mNavBarMode);
setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
@@ -1095,11 +1037,7 @@
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- Dependency.get(PluginManager.class).removePluginListener(this);
Dependency.get(NavigationModeController.class).removeListener(this);
- if (mGestureHelper != null) {
- mGestureHelper.destroy();
- }
setUpSwipeUpOnboarding(false);
for (int i = 0; i < mButtonDispatchers.size(); ++i) {
mButtonDispatchers.valueAt(i).onDestroy();
@@ -1117,21 +1055,6 @@
}
}
- @Override
- public void onPluginConnected(NavGesture plugin, Context context) {
- mGestureHelper = plugin.getGestureHelper();
- updateTaskSwitchHelper();
- }
-
- @Override
- public void onPluginDisconnected(NavGesture plugin) {
- if (mGestureHelper != null) {
- mGestureHelper.destroy();
- mGestureHelper = null;
- }
- updateTaskSwitchHelper();
- }
-
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("NavigationBarView {");
final Rect r = new Rect();
@@ -1154,25 +1077,20 @@
visibilityToString(getCurrentView().getVisibility()),
getCurrentView().getAlpha()));
- pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s darkIntensity=%.2f",
+ pw.println(String.format(" disabled=0x%08x vertical=%s darkIntensity=%.2f",
mDisabledFlags,
mIsVertical ? "true" : "false",
- getMenuButton().isVisible() ? "true" : "false",
getLightTransitionsController().getCurrentDarkIntensity()));
dumpButton(pw, "back", getBackButton());
dumpButton(pw, "home", getHomeButton());
dumpButton(pw, "rcnt", getRecentsButton());
- dumpButton(pw, "menu", getMenuButton());
dumpButton(pw, "rota", getRotateSuggestionButton());
dumpButton(pw, "a11y", getAccessibilityButton());
pw.println(" }");
mContextualButtonGroup.dump(pw);
- if (mGestureHelper != null) {
- mGestureHelper.dump(pw);
- }
mRecentsOnboarding.dump(pw);
mTintController.dump(pw);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
index 7dc71f5..0fe1294 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
@@ -29,7 +29,6 @@
import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
public class NavigationHandle extends View implements ButtonInterface {
private float mDarkIntensity = -1;
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 1194a1d..da9f244 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -18,6 +18,7 @@
import static com.android.systemui.SysUiServiceProvider.getComponent;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import android.animation.Animator;
@@ -59,9 +60,10 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
@@ -348,7 +350,7 @@
super(context, attrs);
setWillNotDraw(!DEBUG);
mInjectionInflationController = injectionInflationController;
- mFalsingManager = FalsingManager.getInstance(context);
+ mFalsingManager = FalsingManagerFactory.getInstance(context);
mPowerManager = context.getSystemService(PowerManager.class);
mWakeUpCoordinator = coordinator;
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
@@ -1316,7 +1318,11 @@
} else if (oldState == StatusBarState.SHADE_LOCKED
&& statusBarState == StatusBarState.KEYGUARD) {
animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- mQs.animateHeaderSlidingOut();
+ // Only animate header if the header is visible. If not, it will partially animate out
+ // the top of QS
+ if (!mQsExpanded) {
+ mQs.animateHeaderSlidingOut();
+ }
} else {
mKeyguardStatusBar.setAlpha(1f);
mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
@@ -2987,7 +2993,7 @@
}
public boolean hasActiveClearableNotifications() {
- return mNotificationStackScroller.hasActiveClearableNotifications();
+ return mNotificationStackScroller.hasActiveClearableNotifications(ROWS_ALL);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 24389f2..c6bbf7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -42,8 +42,9 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.doze.DozeLog;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.StatusBarState;
@@ -212,7 +213,7 @@
0.5f /* maxLengthSeconds */, 0.2f /* speedUpFactor */, 0.6f /* x2 */,
0.84f /* y2 */);
mBounceInterpolator = new BounceInterpolator();
- mFalsingManager = FalsingManager.getInstance(context);
+ mFalsingManager = FalsingManagerFactory.getInstance(context);
mNotificationsDragEnabled =
getResources().getBoolean(R.bool.config_enableNotificationShadeDrag);
mVibratorHelper = Dependency.get(VibratorHelper.class);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 27368de..50e406f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -86,7 +86,7 @@
private static final String TAG = "PhoneStatusBarPolicy";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
+ public static final int LOCATION_STATUS_ICON_ID = PrivacyType.TYPE_LOCATION.getIconId();
private final String mSlotCast;
private final String mSlotHotspot;
@@ -230,10 +230,10 @@
mIconController.setIconVisibility(mSlotDataSaver, false);
// privacy items
- mIconController.setIcon(mSlotMicrophone, R.drawable.stat_sys_mic_none,
+ mIconController.setIcon(mSlotMicrophone, PrivacyType.TYPE_MICROPHONE.getIconId(),
PrivacyType.TYPE_MICROPHONE.getName(mContext));
mIconController.setIconVisibility(mSlotMicrophone, false);
- mIconController.setIcon(mSlotCamera, R.drawable.stat_sys_camera,
+ mIconController.setIcon(mSlotCamera, PrivacyType.TYPE_CAMERA.getIconId(),
PrivacyType.TYPE_CAMERA.getName(mContext));
mIconController.setIconVisibility(mSlotCamera, false);
mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index ce1d638..68eba50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -277,7 +277,7 @@
super.panelExpansionChanged(frac, expanded);
updateScrimFraction();
if ((frac == 0 || frac == 1) && mBar.getNavigationBarView() != null) {
- mBar.getNavigationBarView().onPanelExpandedChange(expanded);
+ mBar.getNavigationBarView().onPanelExpandedChange();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
index 234a968..70cd43a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
@@ -43,6 +43,12 @@
void instantExpandNotificationsPanel();
/**
+ * Collapse the shade animated, showing the bouncer when on {@link StatusBarState#KEYGUARD} or
+ * dismissing {@link StatusBar} when on {@link StatusBarState#SHADE}.
+ */
+ void animateCollapsePanels(int flags, boolean force);
+
+ /**
* If the notifications panel is not fully expanded, collapse it animated.
*
* @return Seems to always return false
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 2524e34..17f0d5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -148,7 +148,7 @@
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingLog;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
@@ -161,6 +161,7 @@
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
@@ -318,6 +319,17 @@
/** If true, the lockscreen will show a distinct wallpaper */
public static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
+ private static final AudioAttributes AUDIO_ATTRIBUTES =
+ new AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ // Temporary fix for b/123870990. No time in this release to
+ // introduce a new vibration type, but we need to distinguish these vibrations
+ // from other haptic feedback vibrations. Fortunately, Alarm vibrations have
+ // exactly the same behavior as we need
+ // TODO: refactor within the scope of b/132170758
+ .setUsage(AudioAttributes.USAGE_ALARM)
+ .build();
+
static {
boolean onlyCoreApps;
try {
@@ -436,7 +448,6 @@
public void onUserSetupChanged() {
final boolean userSetup = mDeviceProvisionedController.isUserSetup(
mDeviceProvisionedController.getCurrentUser());
- // STOPSHIP(kozynski, b/129405675) Remove log
Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for user "
+ mDeviceProvisionedController.getCurrentUser());
if (MULTIUSER_DEBUG) {
@@ -527,6 +538,7 @@
}
if (mKeyguardMonitor.isKeyguardFadingAway()) {
mStatusBarKeyguardViewManager.onKeyguardFadedAway();
+ mStatusBarWindow.onKeyguardFadedAway();
}
}
@@ -713,7 +725,6 @@
result.mFullscreenStackSysUiVisibility, result.mDockedStackSysUiVisibility,
0xffffffff, result.mFullscreenStackBounds, result.mDockedStackBounds,
result.mNavbarColorManagedByIme);
- topAppWindowChanged(mDisplayId, result.mMenuVisible);
// StatusBarManagerService has a back up of IME token and it's restored here.
setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis,
result.mImeBackDisposition, result.mShowImeSwitcher);
@@ -727,11 +738,10 @@
if (DEBUG) {
Log.d(TAG, String.format(
- "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x",
+ "init: icons=%d disabled=0x%08x lights=0x%08x imeButton=0x%08x",
numIcons,
result.mDisabledFlags1,
result.mSystemUiVisibility,
- result.mMenuVisible ? 1 : 0,
result.mImeWindowVis));
}
@@ -763,7 +773,7 @@
putComponent(DozeHost.class, mDozeServiceHost);
mScreenPinningRequest = new ScreenPinningRequest(mContext);
- mFalsingManager = FalsingManager.getInstance(mContext);
+ mFalsingManager = FalsingManagerFactory.getInstance(mContext);
Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
@@ -2235,31 +2245,6 @@
return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE);
}
- public void setLightsOn(boolean on) {
- Log.v(TAG, "setLightsOn(" + on + ")");
- if (on) {
- setSystemUiVisibility(mDisplayId, 0, 0, 0, View.SYSTEM_UI_FLAG_LOW_PROFILE,
- mLastFullscreenStackBounds, mLastDockedStackBounds,
- false /* navbarColorManagedByIme */);
- } else {
- setSystemUiVisibility(mDisplayId, View.SYSTEM_UI_FLAG_LOW_PROFILE, 0, 0,
- View.SYSTEM_UI_FLAG_LOW_PROFILE, mLastFullscreenStackBounds,
- mLastDockedStackBounds, false /* navbarColorManagedByIme */);
- }
- }
-
- @Override
- public void topAppWindowChanged(int displayId, boolean showMenu) {
- if (mDisplayId != displayId) return;
- if (SPEW) {
- Log.d(TAG, "display#" + displayId + ": "
- + (showMenu ? "showing" : "hiding") + " the MENU button");
- }
-
- // See above re: lights-out policy for legacy apps.
- if (showMenu) setLightsOn(true);
- }
-
public static String viewInfo(View v) {
return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom()
+ ") " + v.getWidth() + "x" + v.getHeight() + "]";
@@ -2381,7 +2366,7 @@
mKeyguardUpdateMonitor.dump(fd, pw, args);
}
- FalsingManager.getInstance(mContext).dump(pw);
+ FalsingManagerFactory.getInstance(mContext).dump(pw);
FalsingLog.dump(pw);
pw.println("SharedPreferences:");
@@ -3324,11 +3309,7 @@
@Override
public void showBouncer(boolean scrimmed) {
- if (!mIsOccluded && !scrimmed && mState == StatusBarState.KEYGUARD) {
- animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
- } else {
- mStatusBarKeyguardViewManager.showBouncer(scrimmed);
- }
+ mStatusBarKeyguardViewManager.showBouncer(scrimmed);
}
@Override
@@ -3514,7 +3495,7 @@
// TODO: Figure out way to remove these.
public NavigationBarView getNavigationBarView() {
- return mNavigationBarController.getDefaultNavigationBarView();
+ return mNavigationBarController.getNavigationBarView(mDisplayId);
}
/**
@@ -3699,7 +3680,7 @@
private void vibrateForCameraGesture() {
// Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
- mVibrator.vibrate(mCameraLaunchGestureVibePattern, -1 /* repeat */);
+ mVibrator.vibrate(mCameraLaunchGestureVibePattern, -1 /* repeat */, AUDIO_ATTRIBUTES);
}
/**
@@ -3818,6 +3799,7 @@
public void notifyBiometricAuthModeChanged() {
updateDozing();
updateScrimController();
+ mStatusBarWindow.onBiometricAuthModeChanged(mBiometricUnlockController.isWakeAndUnlock());
}
@VisibleForTesting
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 ce43253..93168db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -40,7 +40,6 @@
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.systemui.DejankUtils;
import com.android.systemui.Dependency;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -192,9 +191,9 @@
KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitorCallback);
mStatusBarStateController.addCallback(this);
Dependency.get(ConfigurationController.class).addCallback(this);
- mLastGesturalNav = QuickStepContract.isGesturalMode(
+ mGesturalNav = QuickStepContract.isGesturalMode(
Dependency.get(NavigationModeController.class).addListener(this));
- mDockManager = SysUiServiceProvider.getComponent(context, DockManager.class);
+ mDockManager = Dependency.get(DockManager.class);
if (mDockManager != null) {
mDockManager.addListener(mDockEventListener);
mIsDocked = mDockManager.isDocked();
@@ -662,7 +661,13 @@
public boolean onBackPressed(boolean hideImmediately) {
if (mBouncer.isShowing()) {
mStatusBar.endAffordanceLaunch();
- reset(hideImmediately);
+ // The second condition is for SIM card locked bouncer
+ if (mBouncer.isScrimmed() && !mBouncer.needsFullscreenBouncer()) {
+ hideBouncer(false);
+ updateStates();
+ } else {
+ reset(hideImmediately);
+ }
return true;
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index e4af15c..e00d439 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import static android.service.notification.NotificationListenerService.REASON_CLICK;
+
import static com.android.systemui.statusbar.phone.StatusBar.getActivityOptions;
import android.app.ActivityManager;
@@ -483,7 +485,7 @@
// We have to post it to the UI thread for synchronization
mMainThreadHandler.post(() -> {
Runnable removeRunnable =
- () -> mEntryManager.performRemoveNotification(notification);
+ () -> mEntryManager.performRemoveNotification(notification, REASON_CLICK);
if (mPresenter.isCollapsing()) {
// To avoid lags we're only performing the remove
// after the shade was collapsed
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 471d511..0865eb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -28,6 +28,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.view.View;
@@ -65,6 +66,7 @@
private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
private final Context mContext;
private final ActivityIntentHelper mActivityIntentHelper;
+ private final NotificationGroupManager mGroupManager;
private View mPendingWorkRemoteInputView;
private View mPendingRemoteInputView;
private final ShadeController mShadeController = Dependency.get(ShadeController.class);
@@ -72,11 +74,12 @@
private final CommandQueue mCommandQueue;
private int mDisabled2;
protected BroadcastReceiver mChallengeReceiver = new ChallengeReceiver();
+ private Handler mMainHandler = new Handler();
/**
*/
@Inject
- public StatusBarRemoteInputCallback(Context context) {
+ public StatusBarRemoteInputCallback(Context context, NotificationGroupManager groupManager) {
mContext = context;
mContext.registerReceiverAsUser(mChallengeReceiver, UserHandle.ALL,
new IntentFilter(ACTION_DEVICE_LOCKED_CHANGED), null, null);
@@ -85,15 +88,15 @@
mCommandQueue = getComponent(context, CommandQueue.class);
mCommandQueue.addCallback(this);
mActivityIntentHelper = new ActivityIntentHelper(mContext);
+ mGroupManager = groupManager;
}
@Override
public void onStateChanged(int state) {
if (state == StatusBarState.SHADE && mStatusBarStateController.leaveOpenOnKeyguardHide()) {
if (!mStatusBarStateController.isKeyguardRequested()) {
- if (mPendingRemoteInputView != null
- && mPendingRemoteInputView.isAttachedToWindow()) {
- mPendingRemoteInputView.post(mPendingRemoteInputView::callOnClick);
+ if (mPendingRemoteInputView != null) {
+ mMainHandler.post(mPendingRemoteInputView::callOnClick);
}
mPendingRemoteInputView = null;
}
@@ -159,6 +162,10 @@
if (mKeyguardMonitor.isShowing()) {
onLockedRemoteInput(row, clickedView);
} else {
+ if (row.isChildInGroup() && !row.areChildrenExpanded()) {
+ // The group isn't expanded, let's make sure it's visible!
+ mGroupManager.toggleGroupExpansion(row.getStatusBarNotification());
+ }
row.setUserExpanded(true);
row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 44996ac..712e962 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -62,7 +62,8 @@
import com.android.systemui.Dependency;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.classifier.FalsingManagerFactory;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.StatusBarState;
@@ -153,7 +154,7 @@
setMotionEventSplittingEnabled(false);
mTransparentSrcPaint.setColor(0);
mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
- mFalsingManager = FalsingManager.getInstance(context);
+ mFalsingManager = FalsingManagerFactory.getInstance(context);
mGestureDetector = new GestureDetector(context, mGestureListener);
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
Dependency.get(TunerService.class).addTunable(mTunable,
@@ -261,7 +262,28 @@
* Propagate {@link StatusBar} pulsing state.
*/
public void setPulsing(boolean pulsing) {
- mLockIcon.setPulsing(pulsing);
+ if (mLockIcon != null) {
+ mLockIcon.setPulsing(pulsing);
+ }
+ }
+
+ /**
+ * Called when the biometric authentication mode changes.
+ * @param wakeAndUnlock If the type is {@link BiometricUnlockController#isWakeAndUnlock()}
+ */
+ public void onBiometricAuthModeChanged(boolean wakeAndUnlock) {
+ if (mLockIcon != null) {
+ mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock);
+ }
+ }
+
+ /**
+ * Called after finished unlocking and the status bar window is already collapsed.
+ */
+ public void onKeyguardFadedAway() {
+ if (mLockIcon != null) {
+ mLockIcon.onKeyguardFadedAway();
+ }
}
public void setStatusBarView(PhoneStatusBarView statusBarView) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 9c7a1e3..3fc9b44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -212,13 +212,15 @@
@Nullable
private String generateTimeRemainingString() {
- if (mEstimate == null) {
- return null;
- }
+ synchronized (mFetchCallbacks) {
+ if (mEstimate == null) {
+ return null;
+ }
- String percentage = NumberFormat.getPercentInstance().format((double) mLevel / 100.0);
- return PowerUtil.getBatteryRemainingShortStringFormatted(
- mContext, mEstimate.getEstimateMillis());
+ String percentage = NumberFormat.getPercentInstance().format((double) mLevel / 100.0);
+ return PowerUtil.getBatteryRemainingShortStringFormatted(
+ mContext, mEstimate.getEstimateMillis());
+ }
}
private void updateEstimateInBackground() {
@@ -230,9 +232,11 @@
mFetchingEstimate = true;
Dependency.get(Dependency.BG_HANDLER).post(() -> {
// Only fetch the estimate if they are enabled
- mEstimate = null;
- if (mEstimates.isHybridNotificationEnabled()) {
- updateEstimate();
+ synchronized (mFetchCallbacks) {
+ mEstimate = null;
+ if (mEstimates.isHybridNotificationEnabled()) {
+ updateEstimate();
+ }
}
mFetchingEstimate = false;
Dependency.get(Dependency.MAIN_HANDLER).post(this::notifyEstimateFetchCallbacks);
@@ -240,9 +244,8 @@
}
private void notifyEstimateFetchCallbacks() {
- String estimate = generateTimeRemainingString();
-
synchronized (mFetchCallbacks) {
+ String estimate = generateTimeRemainingString();
for (EstimateFetchCompletion completion : mFetchCallbacks) {
completion.onBatteryRemainingEstimateRetrieved(estimate);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 8916242..78e845a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -243,6 +243,7 @@
@Override
public void onBluetoothStateChanged(int bluetoothState) {
+ if (DEBUG) Log.d(TAG, "BluetoothStateChanged=" + stateToString(bluetoothState));
mEnabled = bluetoothState == BluetoothAdapter.STATE_ON
|| bluetoothState == BluetoothAdapter.STATE_TURNING_ON;
mState = bluetoothState;
@@ -252,6 +253,7 @@
@Override
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
+ if (DEBUG) Log.d(TAG, "DeviceAdded=" + cachedDevice.getAddress());
cachedDevice.registerCallback(this);
updateConnected();
mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
@@ -259,6 +261,7 @@
@Override
public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
+ if (DEBUG) Log.d(TAG, "DeviceDeleted=" + cachedDevice.getAddress());
mCachedState.remove(cachedDevice);
updateConnected();
mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
@@ -266,6 +269,7 @@
@Override
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
+ if (DEBUG) Log.d(TAG, "DeviceBondStateChanged=" + cachedDevice.getAddress());
mCachedState.remove(cachedDevice);
updateConnected();
mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
@@ -273,12 +277,28 @@
@Override
public void onDeviceAttributesChanged() {
+ if (DEBUG) Log.d(TAG, "DeviceAttributesChanged");
updateConnected();
mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED);
}
@Override
public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
+ if (DEBUG) {
+ Log.d(TAG, "ConnectionStateChanged=" + cachedDevice.getAddress() + " "
+ + stateToString(state));
+ }
+ mCachedState.remove(cachedDevice);
+ updateConnected();
+ mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
+ }
+
+ @Override
+ public void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
+ if (DEBUG) {
+ Log.d(TAG, "ACLConnectionStateChanged=" + cachedDevice.getAddress() + " "
+ + stateToString(state));
+ }
mCachedState.remove(cachedDevice);
updateConnected();
mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
index db2523e..98ab3e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
@@ -61,7 +61,6 @@
mSettingsObserver = new ContentObserver(mainHandler) {
@Override
public void onChange(boolean selfChange, Uri uri, int userId) {
- // STOPSHIP(kozynski, b/129405675) Remove log
Log.d(TAG, "Setting change: " + uri);
if (mUserSetupUri.equals(uri)) {
notifySetupChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
index 2bfc311..568de63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -34,7 +34,6 @@
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.util.FloatProperty;
@@ -79,7 +78,6 @@
private final Paint mIconPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
private final Paint mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
- private final Paint mOvalBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
private final ShadowDrawableState mState;
private AnimatedVectorDrawable mAnimatedDrawable;
@@ -101,7 +99,6 @@
mAnimatedDrawable = (AnimatedVectorDrawable) mState.mChildState.newDrawable().mutate();
setDrawableBounds(mAnimatedDrawable);
}
- mOvalBgPaint.setColor(mState.mDarkColor);
}
public void setDarkIntensity(float intensity) {
@@ -215,6 +212,15 @@
return mState.mBaseWidth + (mState.mShadowSize + Math.abs(mState.mShadowOffsetX)) * 2;
}
+ /** Return if the drawable has oval background. */
+ public boolean hasOvalBg() {
+ return mState.mHasOvalBg;
+ }
+
+ public int getDarkColor() {
+ return mState.mDarkColor;
+ }
+
public boolean canAnimate() {
return mState.mSupportsAnimation;
}
@@ -244,10 +250,6 @@
return;
}
- if (mState.mHasOvalBg) {
- canvas.drawOval(new RectF(bounds), mOvalBgPaint);
- }
-
if (mAnimatedDrawable != null) {
mAnimatedDrawable.draw(canvas);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index 8b86996..0db76ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -73,6 +73,13 @@
private final HashSet<Animator> mRunningAnimations = new HashSet<>();
private final ArrayList<Animator> mTmpArray = new ArrayList<>();
+ public enum Type {
+ OVAL,
+ ROUNDED_RECT
+ }
+
+ private Type mType = Type.ROUNDED_RECT;
+
public KeyButtonRipple(Context ctx, View targetView) {
mMaxWidth = ctx.getResources().getDimensionPixelSize(R.dimen.key_button_ripple_max_width);
mTargetView = targetView;
@@ -86,6 +93,10 @@
mDelayTouchFeedback = delay;
}
+ public void setType(Type type) {
+ mType = type;
+ }
+
private Paint getRipplePaint() {
if (mRipplePaint == null) {
mRipplePaint = new Paint();
@@ -111,9 +122,15 @@
final float ry = horizontal ? cy : radius;
final float corner = horizontal ? cy : cx;
- canvas.drawRoundRect(cx - rx, cy - ry,
- cx + rx, cy + ry,
- corner, corner, p);
+ if (mType == Type.ROUNDED_RECT) {
+ canvas.drawRoundRect(cx - rx, cy - ry, cx + rx, cy + ry, corner, corner, p);
+ } else {
+ canvas.save();
+ canvas.translate(cx, cy);
+ float r = Math.min(rx, ry);
+ canvas.drawOval(-r, -r, r, r, p);
+ canvas.restore();
+ }
}
}
@@ -148,8 +165,16 @@
private void drawHardware(RecordingCanvas c) {
if (mDrawingHardwareGlow) {
- c.drawRoundRect(mLeftProp, mTopProp, mRightProp, mBottomProp, mRxProp, mRyProp,
- mPaintProp);
+ if (mType == Type.ROUNDED_RECT) {
+ c.drawRoundRect(mLeftProp, mTopProp, mRightProp, mBottomProp, mRxProp, mRyProp,
+ mPaintProp);
+ } else {
+ CanvasProperty<Float> cx = CanvasProperty.createFloat(getBounds().width() / 2);
+ CanvasProperty<Float> cy = CanvasProperty.createFloat(getBounds().height() / 2);
+ int d = Math.min(getBounds().width(), getBounds().height());
+ CanvasProperty<Float> r = CanvasProperty.createFloat(1.0f * d / 2);
+ c.drawCircle(cx, cy, r, mPaintProp);
+ }
}
}
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 41fa346..c9579fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -25,6 +25,8 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.hardware.input.InputManager;
@@ -54,9 +56,9 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.statusbar.phone.ButtonInterface;
public class KeyButtonView extends ImageView implements ButtonInterface {
private static final String TAG = KeyButtonView.class.getSimpleName();
@@ -76,6 +78,8 @@
private final OverviewProxyService mOverviewProxyService;
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
private final InputManager mInputManager;
+ private final Paint mOvalBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+ private boolean mHasOvalBg = false;
private final Runnable mCheckLongPress = new Runnable() {
public void run() {
@@ -127,6 +131,7 @@
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
mInputManager = manager;
setBackground(mRipple);
+ setWillNotDraw(false);
forceHasOverlappingRendering(false);
}
@@ -357,7 +362,14 @@
public void setDarkIntensity(float darkIntensity) {
Drawable drawable = getDrawable();
if (drawable != null) {
- ((KeyButtonDrawable) getDrawable()).setDarkIntensity(darkIntensity);
+ KeyButtonDrawable keyButtonDrawable = (KeyButtonDrawable) drawable;
+ keyButtonDrawable.setDarkIntensity(darkIntensity);
+ mHasOvalBg = keyButtonDrawable.hasOvalBg();
+ if (mHasOvalBg) {
+ mOvalBgPaint.setColor(keyButtonDrawable.getDarkColor());
+ }
+ mRipple.setType(keyButtonDrawable.hasOvalBg() ? KeyButtonRipple.Type.OVAL
+ : KeyButtonRipple.Type.ROUNDED_RECT);
// Since we reuse the same drawable for multiple views, we need to invalidate the view
// manually.
@@ -372,9 +384,22 @@
}
@Override
+ public void draw(Canvas canvas) {
+ if (mHasOvalBg) {
+ canvas.save();
+ int cx = (getLeft() + getRight()) / 2;
+ int cy = (getTop() + getBottom()) / 2;
+ canvas.translate(cx, cy);
+ int d = Math.min(getWidth(), getHeight());
+ int r = d / 2;
+ canvas.drawOval(-r, -r, r, r, mOvalBgPaint);
+ canvas.restore();
+ }
+ super.draw(canvas);
+ }
+
+ @Override
public void setVertical(boolean vertical) {
mIsVertical = vertical;
}
}
-
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index c398ad8..c08390f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -284,10 +284,6 @@
@Override
public int getQsCurrentIconId() {
- if (mCurrentState.airplaneMode) {
- return SignalDrawable.getAirplaneModeState(getNumLevels());
- }
-
return getCurrentIconId();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 950f07d..b8a14ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -1012,6 +1012,12 @@
SignalStrength.NUM_SIGNAL_STRENGTH_BINS);
controller.getState().connected = controller.getState().level >= 0;
}
+ if (args.containsKey("inflate")) {
+ for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+ mMobileSignalControllers.valueAt(i).mInflateSignalStrengths =
+ "true".equals(args.getString("inflate"));
+ }
+ }
String activity = args.getString("activity");
if (activity != null) {
controller.getState().dataConnected = true;
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 8380b19..89aa797 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -68,7 +68,8 @@
mThemeManager = new ThemeOverlayManager(
mContext.getSystemService(OverlayManager.class),
AsyncTask.THREAD_POOL_EXECUTOR,
- mContext.getString(R.string.launcher_overlayable_package));
+ mContext.getString(R.string.launcher_overlayable_package),
+ mContext.getString(R.string.themepicker_overlayable_package));
final Handler bgHandler = Dependency.get(Dependency.BG_HANDLER);
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java
index 27e3b2b..930016b 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java
@@ -64,6 +64,9 @@
@VisibleForTesting
static final String OVERLAY_CATEGORY_ICON_LAUNCHER =
"android.theme.customization.icon_pack.launcher";
+ @VisibleForTesting
+ static final String OVERLAY_CATEGORY_ICON_THEME_PICKER =
+ "android.theme.customization.icon_pack.themepicker";
/*
* All theme customization categories used by the system, in order that they should be applied,
@@ -76,7 +79,8 @@
OVERLAY_CATEGORY_COLOR,
OVERLAY_CATEGORY_ICON_ANDROID,
OVERLAY_CATEGORY_ICON_SYSUI,
- OVERLAY_CATEGORY_ICON_SETTINGS);
+ OVERLAY_CATEGORY_ICON_SETTINGS,
+ OVERLAY_CATEGORY_ICON_THEME_PICKER);
/* Categories that need to applied to the current user as well as the system user. */
@VisibleForTesting
@@ -94,12 +98,14 @@
private final OverlayManager mOverlayManager;
private final Executor mExecutor;
private final String mLauncherPackage;
+ private final String mThemePickerPackage;
ThemeOverlayManager(OverlayManager overlayManager, Executor executor,
- String launcherPackage) {
+ String launcherPackage, String themePickerPackage) {
mOverlayManager = overlayManager;
mExecutor = executor;
mLauncherPackage = launcherPackage;
+ mThemePickerPackage = themePickerPackage;
mTargetPackageToCategories.put(ANDROID_PACKAGE, Sets.newHashSet(
OVERLAY_CATEGORY_COLOR, OVERLAY_CATEGORY_FONT,
OVERLAY_CATEGORY_SHAPE, OVERLAY_CATEGORY_ICON_ANDROID));
@@ -109,6 +115,8 @@
Sets.newHashSet(OVERLAY_CATEGORY_ICON_SETTINGS));
mTargetPackageToCategories.put(mLauncherPackage,
Sets.newHashSet(OVERLAY_CATEGORY_ICON_LAUNCHER));
+ mTargetPackageToCategories.put(mThemePickerPackage,
+ Sets.newHashSet(OVERLAY_CATEGORY_ICON_THEME_PICKER));
mCategoryToTargetPackage.put(OVERLAY_CATEGORY_COLOR, ANDROID_PACKAGE);
mCategoryToTargetPackage.put(OVERLAY_CATEGORY_FONT, ANDROID_PACKAGE);
mCategoryToTargetPackage.put(OVERLAY_CATEGORY_SHAPE, ANDROID_PACKAGE);
@@ -116,6 +124,7 @@
mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_SYSUI, SYSUI_PACKAGE);
mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_SETTINGS, SETTINGS_PACKAGE);
mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_LAUNCHER, mLauncherPackage);
+ mCategoryToTargetPackage.put(OVERLAY_CATEGORY_ICON_THEME_PICKER, mThemePickerPackage);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PreviewNavInflater.java b/packages/SystemUI/src/com/android/systemui/tuner/PreviewNavInflater.java
deleted file mode 100644
index e7a695f..0000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/PreviewNavInflater.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.tuner;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.statusbar.phone.NavigationBarInflaterView;
-
-public class PreviewNavInflater extends NavigationBarInflaterView {
-
- public PreviewNavInflater(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- // Immediately remove tuner listening, since this is a preview, all values will be injected
- // manually.
- Dependency.get(TunerService.class).removeTunable(this);
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- // Only a preview, not interactable.
- return true;
- }
-
- @Override
- public void onTuningChanged(String key, String newValue) {
- if (NAV_BAR_VIEWS.equals(key)) {
- // Since this is a preview we might get a bunch of random stuff, validate before sending
- // for inflation.
- if (isValidLayout(newValue)) {
- super.onTuningChanged(key, newValue);
- }
- } else {
- super.onTuningChanged(key, newValue);
- }
- }
-
- private boolean isValidLayout(String newValue) {
- if (newValue == null) {
- return true;
- }
- int separatorCount = 0;
- int lastGravitySeparator = 0;
- for (int i = 0; i < newValue.length(); i++) {
- if (newValue.charAt(i) == GRAVITY_SEPARATOR.charAt(0)) {
- if (i == 0 || (i - lastGravitySeparator) == 1) {
- return false;
- }
- lastGravitySeparator = i;
- separatorCount++;
- }
- }
- return separatorCount == 2 && (newValue.length() - lastGravitySeparator) != 1;
- }
-}
diff --git a/packages/SystemUI/tests/res/values/overlayable_icons_test.xml b/packages/SystemUI/tests/res/values/overlayable_icons_test.xml
index 5cc7976..ba651ac 100644
--- a/packages/SystemUI/tests/res/values/overlayable_icons_test.xml
+++ b/packages/SystemUI/tests/res/values/overlayable_icons_test.xml
@@ -20,6 +20,7 @@
<array name="overlayable_icons">
<item>@drawable/ic_alarm</item>
<item>@drawable/ic_alarm_dim</item>
+ <item>@drawable/ic_arrow_back</item>
<item>@drawable/ic_bluetooth_connected</item>
<item>@drawable/ic_brightness_thumb</item>
<item>@drawable/ic_camera</item>
@@ -42,7 +43,6 @@
<item>@drawable/ic_power_low</item>
<item>@drawable/ic_power_saver</item>
<item>@drawable/ic_qs_bluetooth_connecting</item>
- <item>@drawable/ic_qs_bluetooth_connecting</item>
<item>@drawable/ic_qs_cancel</item>
<item>@drawable/ic_qs_no_sim</item>
<item>@drawable/ic_qs_wifi_0</item>
@@ -63,6 +63,7 @@
<item>@drawable/ic_volume_ringer_mute</item>
<item>@drawable/ic_volume_ringer_vibrate</item>
<item>@drawable/ic_volume_voice</item>
+ <item>@drawable/stat_sys_managed_profile_status</item>
<item>@drawable/stat_sys_mic_none</item>
<item>@drawable/stat_sys_vpn_ic</item>
</array>
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index e312990..db45ad78 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -118,6 +118,7 @@
mKeyguardUpdateMonitor);
// This should not start listening on any of the real dependencies
mCarrierTextController.setListening(mCarrierTextCallback);
+ mCarrierTextController.updateDisplayOpportunisticSubscriptionCarrierText(false);
}
@Test
@@ -358,7 +359,7 @@
.thenReturn(IccCardConstants.State.READY);
mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
- mCarrierTextController.updateDisplayOpportunisticSubscriptionCarrierText();
+ mCarrierTextController.updateDisplayOpportunisticSubscriptionCarrierText(true);
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
@@ -386,10 +387,5 @@
super.setListening(callback);
mKeyguardUpdateMonitor = mKUM;
}
-
- @Override
- public void updateDisplayOpportunisticSubscriptionCarrierText() {
- mDisplayOpportunisticSubscriptionCarrierText = true;
- }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
index 76f1684..3330d1e 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
@@ -84,7 +84,6 @@
when(mMockInjectionInflationController.injectable(any())).thenReturn(inflater);
mFakeDockManager = new DockManagerFake();
- getContext().putComponent(DockManager.class, mFakeDockManager);
mCurrentUser = new MutableLiveData<>();
mCurrentUser.setValue(MAIN_USER_ID);
@@ -92,7 +91,7 @@
mClockManager = new ClockManager(getContext(), mMockInjectionInflationController,
mMockPluginManager, mMockColorExtractor, mMockContentResolver,
- mMockCurrentUserObserable, mMockSettingsWrapper);
+ mMockCurrentUserObserable, mMockSettingsWrapper, mFakeDockManager);
mClockManager.addOnClockChangedListener(mMockListener1);
mClockManager.addOnClockChangedListener(mMockListener2);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 8b0ba94..35a1516 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -18,13 +18,20 @@
import static android.app.Notification.FLAG_BUBBLE;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
+
+import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -50,6 +57,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -95,10 +103,13 @@
private FrameLayout mStatusBarView;
@Captor
private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
+ @Captor
+ private ArgumentCaptor<NotificationRemoveInterceptor> mRemoveInterceptorCaptor;
private TestableBubbleController mBubbleController;
private StatusBarWindowController mStatusBarWindowController;
private NotificationEntryListener mEntryListener;
+ private NotificationRemoveInterceptor mRemoveInterceptor;
private NotificationTestHelper mNotificationTestHelper;
private ExpandableNotificationRow mRow;
@@ -167,6 +178,10 @@
verify(mNotificationEntryManager, atLeastOnce())
.addNotificationEntryListener(mEntryListenerCaptor.capture());
mEntryListener = mEntryListenerCaptor.getValue();
+ // And the remove interceptor
+ verify(mNotificationEntryManager, atLeastOnce())
+ .setNotificationRemoveInterceptor(mRemoveInterceptorCaptor.capture());
+ mRemoveInterceptor = mRemoveInterceptorCaptor.getValue();
}
@Test
@@ -199,6 +214,27 @@
}
@Test
+ public void testRemoveBubble_withDismissedNotif() {
+ mEntryListener.onPendingEntryAdded(mRow.getEntry());
+ mBubbleController.updateBubble(mRow.getEntry());
+
+ assertTrue(mBubbleController.hasBubbles());
+ assertTrue(mRow.getEntry().showInShadeWhenBubble());
+
+ // Make it look like dismissed notif
+ mRow.getEntry().setShowInShadeWhenBubble(false);
+
+ // Now remove the bubble
+ mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+
+ // Since the notif is dismissed, once the bubble is removed, performRemoveNotification gets
+ // called to really remove the notif
+ verify(mNotificationEntryManager, times(1)).performRemoveNotification(
+ mRow.getEntry().notification, UNDEFINED_DISMISS_REASON);
+ assertFalse(mBubbleController.hasBubbles());
+ }
+
+ @Test
public void testDismissStack() {
mBubbleController.updateBubble(mRow.getEntry());
verify(mNotificationEntryManager, times(1)).updateNotifications();
@@ -260,22 +296,22 @@
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleController.expandStack();
assertTrue(mBubbleController.isStackExpanded());
- verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
- // First added is the one that is expanded
- assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
- assertFalse(mRow.getEntry().showInShadeWhenBubble());
-
- // Switch which bubble is expanded
- mBubbleController.selectBubble(mRow2.getEntry().key);
- stackView.setExpandedBubble(mRow2.getEntry());
+ // Last added is the one that is expanded
assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
assertFalse(mRow2.getEntry().showInShadeWhenBubble());
+ // Switch which bubble is expanded
+ mBubbleController.selectBubble(mRow.getEntry().key);
+ stackView.setExpandedBubble(mRow.getEntry());
+ assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
+ assertFalse(mRow.getEntry().showInShadeWhenBubble());
+
// collapse for previous bubble
- verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
// expand for selected bubble
- verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
// Collapse
mBubbleController.collapseStack();
@@ -316,27 +352,27 @@
mBubbleController.expandStack();
assertTrue(mBubbleController.isStackExpanded());
- verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
- // First added is the one that is expanded
- assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
- assertFalse(mRow.getEntry().showInShadeWhenBubble());
+ // Last added is the one that is expanded
+ assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
+ assertFalse(mRow2.getEntry().showInShadeWhenBubble());
// Dismiss currently expanded
mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
BubbleController.DISMISS_USER_GESTURE);
- verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
- // Make sure next bubble is selected
- assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
- verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
+ // Make sure first bubble is selected
+ assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
+ verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
// Dismiss that one
mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
BubbleController.DISMISS_USER_GESTURE);
// Make sure state changes and collapse happens
- verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
assertFalse(mBubbleController.hasBubbles());
}
@@ -455,8 +491,7 @@
mBubbleController.updateBubble(mRow.getEntry());
// Simulate notification cancellation.
- mEntryListener.onEntryRemoved(mRow.getEntry(), null /* notificationVisibility (unused) */,
- false /* removedbyUser */);
+ mRemoveInterceptor.onNotificationRemoveRequested(mRow.getEntry().key, REASON_APP_CANCEL);
mBubbleController.expandStackAndSelectBubble(key);
}
@@ -511,6 +546,83 @@
verify(mDeleteIntent, never()).send();
}
+ @Test
+ public void testRemoveBubble_succeeds_appCancel() {
+ mEntryListener.onPendingEntryAdded(mRow.getEntry());
+ mBubbleController.updateBubble(mRow.getEntry());
+
+ assertTrue(mBubbleController.hasBubbles());
+
+ boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
+ mRow.getEntry().key, REASON_APP_CANCEL);
+
+ // Cancels always remove so no need to intercept
+ assertFalse(intercepted);
+ assertFalse(mBubbleController.hasBubbles());
+ }
+
+ @Test
+ public void removeBubble_fails_clearAll() {
+ mEntryListener.onPendingEntryAdded(mRow.getEntry());
+ mBubbleController.updateBubble(mRow.getEntry());
+
+ assertTrue(mBubbleController.hasBubbles());
+ assertTrue(mRow.getEntry().showInShadeWhenBubble());
+
+ boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
+ mRow.getEntry().key, REASON_CANCEL_ALL);
+
+ // Intercept!
+ assertTrue(intercepted);
+ // Should update show in shade state
+ assertFalse(mRow.getEntry().showInShadeWhenBubble());
+
+ verify(mNotificationEntryManager, never()).performRemoveNotification(
+ any(), anyInt());
+ assertTrue(mBubbleController.hasBubbles());
+ }
+
+ @Test
+ public void removeBubble_fails_userDismissNotif() {
+ mEntryListener.onPendingEntryAdded(mRow.getEntry());
+ mBubbleController.updateBubble(mRow.getEntry());
+
+ assertTrue(mBubbleController.hasBubbles());
+ assertTrue(mRow.getEntry().showInShadeWhenBubble());
+
+ boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
+ mRow.getEntry().key, REASON_CANCEL);
+
+ // Intercept!
+ assertTrue(intercepted);
+ // Should update show in shade state
+ assertFalse(mRow.getEntry().showInShadeWhenBubble());
+
+ verify(mNotificationEntryManager, never()).performRemoveNotification(
+ any(), anyInt());
+ assertTrue(mBubbleController.hasBubbles());
+ }
+
+ @Test
+ public void removeBubble_succeeds_userDismissBubble_userDimissNotif() {
+ mEntryListener.onPendingEntryAdded(mRow.getEntry());
+ mBubbleController.updateBubble(mRow.getEntry());
+
+ assertTrue(mBubbleController.hasBubbles());
+ assertTrue(mRow.getEntry().showInShadeWhenBubble());
+
+ // Dismiss the bubble
+ mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+ assertFalse(mBubbleController.hasBubbles());
+
+ // Dismiss the notification
+ boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
+ mRow.getEntry().key, REASON_CANCEL);
+
+ // It's no longer a bubble so we shouldn't intercept
+ assertFalse(intercepted);
+ }
+
static class TestableBubbleController extends BubbleController {
// Let's assume surfaces can be synchronized immediately.
TestableBubbleController(Context context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index d6dac2f..33b2e6e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -16,12 +16,18 @@
package com.android.systemui.bubbles;
+import static com.android.systemui.bubbles.BubbleController.DISMISS_AGED;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -48,6 +54,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.List;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -108,6 +116,628 @@
// Used by BubbleData to set lastAccessedTime
when(mTimeSource.currentTimeMillis()).thenReturn(1000L);
mBubbleData.setTimeSource(mTimeSource);
+
+ // Assert baseline starting state
+ assertThat(mBubbleData.hasBubbles()).isFalse();
+ assertThat(mBubbleData.isExpanded()).isFalse();
+ assertThat(mBubbleData.getSelectedBubble()).isNull();
+ }
+
+ @Test
+ public void testAddBubble() {
+ // Setup
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+
+ // Verify
+ verify(mListener).onBubbleAdded(eq(mBubbleA1));
+ verify(mListener).onSelectionChanged(eq(mBubbleA1));
+ verify(mListener).apply();
+ }
+
+ @Test
+ public void testRemoveBubble() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryA2, 2000);
+ sendUpdatedEntryAtTime(mEntryA3, 3000);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
+
+ // Verify
+ verify(mListener).onBubbleRemoved(eq(mBubbleA1), eq(BubbleController.DISMISS_USER_GESTURE));
+ verify(mListener).apply();
+ }
+
+ // COLLAPSED / ADD
+
+ /**
+ * Verifies that the number of bubbles is not allowed to exceed the maximum. The limit is
+ * enforced by expiring the bubble which was least recently updated (lowest timestamp).
+ */
+ @Test
+ public void test_collapsed_addBubble_atMaxBubbles_expiresOldest() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryA2, 2000);
+ sendUpdatedEntryAtTime(mEntryA3, 3000);
+ sendUpdatedEntryAtTime(mEntryB1, 4000);
+ sendUpdatedEntryAtTime(mEntryB2, 5000);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryC1, 6000);
+ verify(mListener).onBubbleRemoved(eq(mBubbleA1), eq(DISMISS_AGED));
+ }
+
+ /**
+ * Verifies that new bubbles insert to the left when collapsed, carrying along grouped bubbles.
+ * <p>
+ * Placement within the list is based on lastUpdate (post time of the notification), descending
+ * order (with most recent first).
+ *
+ * @see #test_expanded_addBubble_sortAndGrouping_newGroup()
+ * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+ */
+ @Test
+ public void test_collapsed_addBubble_sortAndGrouping() {
+ // Setup
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ verify(mListener, never()).onOrderChanged(anyList());
+
+ reset(mListener);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleB1, mBubbleA1)));
+
+ reset(mListener);
+ sendUpdatedEntryAtTime(mEntryB2, 3000);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleB2, mBubbleB1, mBubbleA1)));
+
+ reset(mListener);
+ sendUpdatedEntryAtTime(mEntryA2, 4000);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1)));
+ }
+
+ /**
+ * Verifies that new bubbles insert to the left when collapsed, carrying along grouped bubbles.
+ * Additionally, any bubble which is ongoing is considered "newer" than any non-ongoing bubble.
+ * <p>
+ * Because of the ongoing bubble, the new bubble cannot be placed in the first position. This
+ * causes the 'B' group to remain last, despite having a new button added.
+ *
+ * @see #test_expanded_addBubble_sortAndGrouping_newGroup()
+ * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+ */
+ @Test
+ public void test_collapsed_addBubble_sortAndGrouping_withOngoing() {
+ // Setup
+ mBubbleData.setListener(mListener);
+
+ // Test
+ setOngoing(mEntryA1, true);
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ verify(mListener, never()).onOrderChanged(anyList());
+
+ reset(mListener);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ verify(mListener, never()).onOrderChanged(eq(listOf(mBubbleA1, mBubbleB1)));
+
+ reset(mListener);
+ sendUpdatedEntryAtTime(mEntryB2, 3000);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleA1, mBubbleB2, mBubbleB1)));
+
+ reset(mListener);
+ sendUpdatedEntryAtTime(mEntryA2, 4000);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleA1, mBubbleA2, mBubbleB2, mBubbleB1)));
+ }
+
+ /**
+ * Verifies that new bubbles become the selected bubble when they appear when the stack is in
+ * the collapsed state.
+ *
+ * @see #test_collapsed_updateBubble_selectionChanges()
+ * @see #test_collapsed_updateBubble_noSelectionChanges_withOngoing()
+ */
+ @Test
+ public void test_collapsed_addBubble_selectionChanges() {
+ // Setup
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ verify(mListener).onSelectionChanged(eq(mBubbleA1));
+
+ reset(mListener);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ verify(mListener).onSelectionChanged(eq(mBubbleB1));
+
+ reset(mListener);
+ sendUpdatedEntryAtTime(mEntryB2, 3000);
+ verify(mListener).onSelectionChanged(eq(mBubbleB2));
+
+ reset(mListener);
+ sendUpdatedEntryAtTime(mEntryA2, 4000);
+ verify(mListener).onSelectionChanged(eq(mBubbleA2));
+ }
+ /**
+ * Verifies that while collapsed, the selection will not change if the selected bubble is
+ * ongoing. It remains the top bubble and as such remains selected.
+ *
+ * @see #test_collapsed_addBubble_selectionChanges()
+ */
+ @Test
+ public void test_collapsed_addBubble_noSelectionChanges_withOngoing() {
+ // Setup
+ setOngoing(mEntryA1, true);
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ sendUpdatedEntryAtTime(mEntryB2, 3000);
+ sendUpdatedEntryAtTime(mEntryA2, 4000);
+ verify(mListener, never()).onSelectionChanged(any(Bubble.class));
+ assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1); // selection unchanged
+ }
+
+ // COLLAPSED / REMOVE
+
+ /**
+ * Verifies that groups may reorder when bubbles are removed, while the stack is in the
+ * collapsed state.
+ */
+ @Test
+ public void test_collapsed_removeBubble_sortAndGrouping() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ sendUpdatedEntryAtTime(mEntryB2, 3000);
+ sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
+ mBubbleData.setListener(mListener);
+
+ // Test
+ mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_USER_GESTURE);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleB2, mBubbleB1, mBubbleA1)));
+ }
+
+
+ /**
+ * Verifies that onOrderChanged is not called when a bubble is removed if the removal does not
+ * cause other bubbles to change position.
+ */
+ @Test
+ public void test_collapsed_removeOldestBubble_doesNotCallOnOrderChanged() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ sendUpdatedEntryAtTime(mEntryB2, 3000);
+ sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
+ mBubbleData.setListener(mListener);
+
+ // Test
+ mBubbleData.notificationEntryRemoved(mEntryB1, BubbleController.DISMISS_USER_GESTURE);
+ verify(mListener, never()).onOrderChanged(anyList());
+ }
+
+ /**
+ * Verifies that bubble ordering reverts to normal when an ongoing bubble is removed. A group
+ * which has a newer bubble may move to the front after the ongoing bubble is removed.
+ */
+ @Test
+ public void test_collapsed_removeBubble_sortAndGrouping_withOngoing() {
+ // Setup
+ setOngoing(mEntryA1, true);
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryA2, 2000);
+ sendUpdatedEntryAtTime(mEntryB1, 3000);
+ sendUpdatedEntryAtTime(mEntryB2, 4000); // [A1*, A2, B2, B1]
+ mBubbleData.setListener(mListener);
+
+ // Test
+ mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_NOTIF_CANCEL);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleB2, mBubbleB1, mBubbleA2)));
+ }
+
+ /**
+ * Verifies that when the selected bubble is removed with the stack in the collapsed state,
+ * the selection moves to the next most-recently updated bubble.
+ */
+ @Test
+ public void test_collapsed_removeBubble_selectionChanges() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ sendUpdatedEntryAtTime(mEntryB2, 3000);
+ sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
+ mBubbleData.setListener(mListener);
+
+ // Test
+ mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_NOTIF_CANCEL);
+ verify(mListener).onSelectionChanged(eq(mBubbleB2));
+ }
+
+ // COLLAPSED / UPDATE
+
+ /**
+ * Verifies that bubble and group ordering may change with updates while the stack is in the
+ * collapsed state.
+ */
+ @Test
+ public void test_collapsed_updateBubble_orderAndGrouping() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ sendUpdatedEntryAtTime(mEntryB2, 3000);
+ sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryB1, 5000);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleB1, mBubbleB2, mBubbleA2, mBubbleA1)));
+
+ reset(mListener);
+ sendUpdatedEntryAtTime(mEntryA1, 6000);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleA1, mBubbleA2, mBubbleB1, mBubbleB2)));
+ }
+
+ /**
+ * Verifies that selection tracks the most recently updated bubble while in the collapsed state.
+ */
+ @Test
+ public void test_collapsed_updateBubble_selectionChanges() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ sendUpdatedEntryAtTime(mEntryB2, 3000);
+ sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryB1, 5000);
+ verify(mListener).onSelectionChanged(eq(mBubbleB1));
+
+ reset(mListener);
+ sendUpdatedEntryAtTime(mEntryA1, 6000);
+ verify(mListener).onSelectionChanged(eq(mBubbleA1));
+ }
+
+ /**
+ * Verifies that selection does not change in response to updates when collapsed, if the
+ * selected bubble is ongoing.
+ */
+ @Test
+ public void test_collapsed_updateBubble_noSelectionChanges_withOngoing() {
+ // Setup
+ setOngoing(mEntryA1, true);
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ sendUpdatedEntryAtTime(mEntryB2, 3000);
+ sendUpdatedEntryAtTime(mEntryA2, 4000); // [A1*, A2, B2, B1]
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryB2, 5000); // [A1*, A2, B2, B1]
+ verify(mListener, never()).onSelectionChanged(any(Bubble.class));
+ }
+
+ /**
+ * Verifies that a request to expand the stack has no effect if there are no bubbles.
+ */
+ @Test
+ public void test_collapsed_expansion_whenEmpty_doesNothing() {
+ assertThat(mBubbleData.hasBubbles()).isFalse();
+ changeExpandedStateAtTime(true, 2000L);
+
+ verify(mListener, never()).onExpandedChanged(anyBoolean());
+ verify(mListener, never()).apply();
+ }
+
+ @Test
+ public void test_collapsed_removeLastBubble_clearsSelectedBubble() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
+
+ // Verify the selection was cleared.
+ verify(mListener).onSelectionChanged(isNull());
+ }
+
+ // EXPANDED / ADD
+
+ /**
+ * Verifies that bubbles added as part of a new group insert before existing groups while
+ * expanded.
+ * <p>
+ * Placement within the list is based on lastUpdate (post time of the notification), descending
+ * order (with most recent first).
+ *
+ * @see #test_collapsed_addBubble_sortAndGrouping()
+ * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+ */
+ @Test
+ public void test_expanded_addBubble_sortAndGrouping_newGroup() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryA2, 2000);
+ sendUpdatedEntryAtTime(mEntryB1, 3000); // [B1, A2, A1]
+ changeExpandedStateAtTime(true, 4000L);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryC1, 4000);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleC1, mBubbleB1, mBubbleA2, mBubbleA1)));
+ }
+
+ /**
+ * Verifies that bubbles added as part of a new group insert before existing groups while
+ * expanded, but not before any groups with ongoing bubbles.
+ *
+ * @see #test_collapsed_addBubble_sortAndGrouping_withOngoing()
+ * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+ */
+ @Test
+ public void test_expanded_addBubble_sortAndGrouping_newGroup_withOngoing() {
+ // Setup
+ setOngoing(mEntryA1, true);
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryA2, 2000);
+ sendUpdatedEntryAtTime(mEntryB1, 3000); // [A1*, A2, B1]
+ changeExpandedStateAtTime(true, 4000L);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryC1, 4000);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleA1, mBubbleA2, mBubbleC1, mBubbleB1)));
+ }
+
+ /**
+ * Verifies that bubbles added as part of an existing group insert to the beginning of that
+ * group. The order of groups within the list must not change while in the expanded state.
+ *
+ * @see #test_collapsed_addBubble_sortAndGrouping()
+ * @see #test_expanded_addBubble_sortAndGrouping_newGroup()
+ */
+ @Test
+ public void test_expanded_addBubble_sortAndGrouping_existingGroup() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryA2, 2000);
+ sendUpdatedEntryAtTime(mEntryB1, 3000); // [B1, A2, A1]
+ changeExpandedStateAtTime(true, 4000L);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryA3, 4000);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleB1, mBubbleA3, mBubbleA2, mBubbleA1)));
+ }
+
+ // EXPANDED / UPDATE
+
+ /**
+ * Verifies that updates to bubbles while expanded do not result in any change to sorting
+ * or grouping of bubbles or sorting of groups.
+ *
+ * @see #test_collapsed_addBubble_sortAndGrouping()
+ * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+ */
+ @Test
+ public void test_expanded_updateBubble_sortAndGrouping_noChanges() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryA2, 2000);
+ sendUpdatedEntryAtTime(mEntryB1, 3000);
+ sendUpdatedEntryAtTime(mEntryB2, 4000); // [B2, B1, A2, A1]
+ changeExpandedStateAtTime(true, 5000L);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryA1, 4000);
+ verify(mListener, never()).onOrderChanged(anyList());
+ }
+
+ /**
+ * Verifies that updates to bubbles while expanded do not result in any change to selection.
+ *
+ * @see #test_collapsed_addBubble_selectionChanges()
+ * @see #test_collapsed_updateBubble_noSelectionChanges_withOngoing()
+ */
+ @Test
+ public void test_expanded_updateBubble_noSelectionChanges() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryA2, 2000);
+ sendUpdatedEntryAtTime(mEntryB1, 3000);
+ sendUpdatedEntryAtTime(mEntryB2, 4000); // [B2, B1, A2, A1]
+ changeExpandedStateAtTime(true, 5000L);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ sendUpdatedEntryAtTime(mEntryA1, 6000);
+ sendUpdatedEntryAtTime(mEntryA2, 7000);
+ sendUpdatedEntryAtTime(mEntryB1, 8000);
+ verify(mListener, never()).onSelectionChanged(any(Bubble.class));
+ }
+
+ // EXPANDED / REMOVE
+
+ /**
+ * Verifies that removing a bubble while expanded does not result in reordering of groups
+ * or any of the remaining bubbles.
+ *
+ * @see #test_collapsed_addBubble_sortAndGrouping()
+ * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+ */
+ @Test
+ public void test_expanded_removeBubble_sortAndGrouping() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ sendUpdatedEntryAtTime(mEntryA2, 3000);
+ sendUpdatedEntryAtTime(mEntryB2, 4000); // [B2, B1, A2, A1]
+ changeExpandedStateAtTime(true, 5000L);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ mBubbleData.notificationEntryRemoved(mEntryB2, BubbleController.DISMISS_USER_GESTURE);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleB1, mBubbleA2, mBubbleA1)));
+ }
+
+ /**
+ * Verifies that removing the selected bubble while expanded causes another bubble to become
+ * selected. The replacement selection is the bubble which appears at the same index as the
+ * previous one, or the previous index if this was the last position.
+ *
+ * @see #test_collapsed_addBubble_sortAndGrouping()
+ * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+ */
+ @Test
+ public void test_expanded_removeBubble_selectionChanges_whenSelectedRemoved() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ sendUpdatedEntryAtTime(mEntryA2, 3000);
+ sendUpdatedEntryAtTime(mEntryB2, 4000);
+ changeExpandedStateAtTime(true, 5000L);
+ mBubbleData.setSelectedBubble(mBubbleA2); // [B2, B1, ^A2, A1]
+ mBubbleData.setListener(mListener);
+
+ // Test
+ mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_USER_GESTURE);
+ verify(mListener).onSelectionChanged(mBubbleA1);
+
+ reset(mListener);
+ mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
+ verify(mListener).onSelectionChanged(mBubbleB1);
+ }
+
+ @Test
+ public void test_expandAndCollapse_callsOnExpandedChanged() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ changeExpandedStateAtTime(true, 3000L);
+ verify(mListener).onExpandedChanged(eq(true));
+
+ reset(mListener);
+ changeExpandedStateAtTime(false, 4000L);
+ verify(mListener).onExpandedChanged(eq(false));
+ }
+
+ /**
+ * Verifies that transitions between the collapsed and expanded state maintain sorting and
+ * grouping rules.
+ * <p>
+ * While collapsing, sorting is applied since no sorting happens while expanded. The resulting
+ * state is the new expanded ordering. This state is saved and restored if possible when next
+ * expanded.
+ * <p>
+ * When the stack transitions to the collapsed state, the selected bubble is brought to the top.
+ * Bubbles within the same group should move up with it.
+ * <p>
+ * When the stack transitions back to the expanded state, the previous ordering is restored, as
+ * long as no changes have been made (adds, removes or updates) while in the collapsed state.
+ */
+ @Test
+ public void test_expansionChanges() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ sendUpdatedEntryAtTime(mEntryA2, 3000);
+ sendUpdatedEntryAtTime(mEntryB2, 4000);
+ changeExpandedStateAtTime(true, 5000L); // [B2=4000, B1=2000, A2=3000, A1=1000]
+ sendUpdatedEntryAtTime(mEntryB1, 6000); // [B2=4000, B1=6000*, A2=3000, A1=1000]
+ setCurrentTime(7000);
+ mBubbleData.setSelectedBubble(mBubbleA2);
+ mBubbleData.setListener(mListener);
+ assertThat(mBubbleData.getBubbles()).isEqualTo(
+ listOf(mBubbleB2, mBubbleB1, mBubbleA2, mBubbleA1));
+
+ // Test
+
+ // At this point, B1 has been updated but sorting has not been changed because the
+ // stack is expanded. When next collapsed, sorting will be applied and saved, just prior
+ // to moving the selected bubble to the top (first).
+ //
+ // In this case, the expected re-expand state will be: [B1, B2, A2*, A1]
+ //
+ // That state is restored as long as no changes occur (add/remove/update) while in
+ // the collapsed state.
+ //
+ // collapse -> selected bubble (A2) moves first.
+ changeExpandedStateAtTime(false, 8000L);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleA2, mBubbleA1, mBubbleB1, mBubbleB2)));
+
+ // expand -> "original" order/grouping restored
+ reset(mListener);
+ changeExpandedStateAtTime(true, 10000L);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleB1, mBubbleB2, mBubbleA2, mBubbleA1)));
+ }
+
+ /**
+ * When a change occurs while collapsed (any update, add, remove), the previous expanded
+ * order and grouping becomes invalidated, and the order and grouping when next expanded will
+ * remain the same as collapsed.
+ */
+ @Test
+ public void test_expansionChanges_withUpdatesWhileCollapsed() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryB1, 2000);
+ sendUpdatedEntryAtTime(mEntryA2, 3000);
+ sendUpdatedEntryAtTime(mEntryB2, 4000);
+ changeExpandedStateAtTime(true, 5000L); // [B2=4000, B1=2000, A2=3000, A1=1000]
+ sendUpdatedEntryAtTime(mEntryB1, 6000); // [B2=4000, B1=*6000, A2=3000, A1=1000]
+ setCurrentTime(7000);
+ mBubbleData.setSelectedBubble(mBubbleA2); // [B2, B1, ^A2, A1]
+ mBubbleData.setListener(mListener);
+
+ // Test
+
+ // At this point, B1 has been updated but sorting has not been changed because the
+ // stack is expanded. When next collapsed, sorting will be applied and saved, just prior
+ // to moving the selected bubble to the top (first).
+ //
+ // In this case, the expected re-expand state will be: [B1, B2, A2*, A1]
+ //
+ // That state is restored as long as no changes occur (add/remove/update) while in
+ // the collapsed state.
+ //
+ // collapse -> selected bubble (A2) moves first.
+ changeExpandedStateAtTime(false, 8000L);
+ verify(mListener).onOrderChanged(eq(listOf(mBubbleA2, mBubbleA1, mBubbleB1, mBubbleB2)));
+
+ // An update occurs, which causes sorting, and this invalidates the previously saved order.
+ sendUpdatedEntryAtTime(mEntryA2, 9000);
+
+ // No order changes when expanding because the new sorted order remains.
+ reset(mListener);
+ changeExpandedStateAtTime(true, 10000L);
+ verify(mListener, never()).onOrderChanged(anyList());
+ }
+
+ @Test
+ public void test_expanded_removeLastBubble_collapsesStack() {
+ // Setup
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ changeExpandedStateAtTime(true, 2000);
+ mBubbleData.setListener(mListener);
+
+ // Test
+ mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
+ verify(mListener).onExpandedChanged(eq(false));
}
private NotificationEntry createBubbleEntry(int userId, String notifKey, String packageName) {
@@ -155,553 +785,22 @@
return new NotificationEntry(sbn);
}
+ private void setCurrentTime(long time) {
+ when(mTimeSource.currentTimeMillis()).thenReturn(time);
+ }
+
private void sendUpdatedEntryAtTime(NotificationEntry entry, long postTime) {
setPostTime(entry, postTime);
mBubbleData.notificationEntryUpdated(entry);
}
private void changeExpandedStateAtTime(boolean shouldBeExpanded, long time) {
- when(mTimeSource.currentTimeMillis()).thenReturn(time);
+ setCurrentTime(time);
mBubbleData.setExpanded(shouldBeExpanded);
}
- @Test
- public void testAddBubble() {
- // Setup
- mBubbleData.setListener(mListener);
-
- // Test
- setPostTime(mEntryA1, 1000);
- mBubbleData.notificationEntryUpdated(mEntryA1);
-
- // Verify
- verify(mListener).onBubbleAdded(eq(mBubbleA1));
- verify(mListener).onSelectionChanged(eq(mBubbleA1));
- verify(mListener).apply();
- }
-
- @Test
- public void testRemoveBubble() {
- // Setup
- mBubbleData.notificationEntryUpdated(mEntryA1);
- mBubbleData.notificationEntryUpdated(mEntryA2);
- mBubbleData.notificationEntryUpdated(mEntryA3);
- mBubbleData.setListener(mListener);
-
- // Test
- mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
-
- // Verify
- verify(mListener).onBubbleRemoved(eq(mBubbleA1), eq(BubbleController.DISMISS_USER_GESTURE));
- verify(mListener).onSelectionChanged(eq(mBubbleA2));
- verify(mListener).apply();
- }
-
- @Test
- public void test_collapsed_addBubble_atMaxBubbles_expiresLeastActive() {
- // Given
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- sendUpdatedEntryAtTime(mEntryA2, 2000);
- sendUpdatedEntryAtTime(mEntryA3, 3000);
- sendUpdatedEntryAtTime(mEntryB1, 4000);
- sendUpdatedEntryAtTime(mEntryB2, 5000);
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1);
-
- // When
- sendUpdatedEntryAtTime(mEntryC1, 6000);
-
- // Then
- // A2 is removed. A1 is oldest but is the selected bubble.
- assertThat(mBubbleData.getBubbles()).doesNotContain(mBubbleA2);
- }
-
- @Test
- public void test_collapsed_expand_whenEmpty_doesNothing() {
- assertThat(mBubbleData.hasBubbles()).isFalse();
- changeExpandedStateAtTime(true, 2000L);
-
- verify(mListener, never()).onExpandedChanged(anyBoolean());
- verify(mListener, never()).apply();
- }
-
- // New bubble while stack is collapsed
- @Test
- public void test_collapsed_addBubble() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- // When
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- sendUpdatedEntryAtTime(mEntryB1, 2000);
- sendUpdatedEntryAtTime(mEntryB2, 3000);
- sendUpdatedEntryAtTime(mEntryA2, 4000);
-
- // Then
- // New bubbles move to front when collapsed, bringing bubbles from the same app along
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1));
- }
-
- // New bubble while collapsed with ongoing bubble present
- @Test
- public void test_collapsed_addBubble_withOngoing() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- // When
- setOngoing(mEntryA1, true);
- setPostTime(mEntryA1, 1000);
- mBubbleData.notificationEntryUpdated(mEntryA1);
- setPostTime(mEntryB1, 2000);
- mBubbleData.notificationEntryUpdated(mEntryB1);
- setPostTime(mEntryB2, 3000);
- mBubbleData.notificationEntryUpdated(mEntryB2);
- setPostTime(mEntryA2, 4000);
- mBubbleData.notificationEntryUpdated(mEntryA2);
-
- // Then
- // New bubbles move to front, but stay behind any ongoing bubbles.
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA1, mBubbleA2, mBubbleB2, mBubbleB1));
- }
-
- // Remove the selected bubble (middle bubble), while the stack is collapsed.
- @Test
- public void test_collapsed_removeBubble_selected() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- setPostTime(mEntryA1, 1000);
- mBubbleData.notificationEntryUpdated(mEntryA1);
-
- setPostTime(mEntryB1, 2000);
- mBubbleData.notificationEntryUpdated(mEntryB1);
-
- setPostTime(mEntryB2, 3000);
- mBubbleData.notificationEntryUpdated(mEntryB2);
-
- setPostTime(mEntryA2, 4000);
- mBubbleData.notificationEntryUpdated(mEntryA2);
-
- mBubbleData.setSelectedBubble(mBubbleB2);
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1));
-
- // When
- mBubbleData.notificationEntryRemoved(mEntryB2, BubbleController.DISMISS_USER_GESTURE);
-
- // Then
- // (Selection remains in the same position)
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleB1);
- }
-
- // Remove the selected bubble (last bubble), while the stack is collapsed.
- @Test
- public void test_collapsed_removeSelectedBubble_inLastPosition() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- sendUpdatedEntryAtTime(mEntryB1, 2000);
- sendUpdatedEntryAtTime(mEntryB2, 3000);
- sendUpdatedEntryAtTime(mEntryA2, 4000);
-
- mBubbleData.setSelectedBubble(mBubbleB1);
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1));
-
- // When
- mBubbleData.notificationEntryRemoved(mEntryB1, BubbleController.DISMISS_USER_GESTURE);
-
- // Then
- // (Selection is forced to move to previous)
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleB2);
- }
-
- @Test
- public void test_collapsed_addBubble_ongoing() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- // When
- setPostTime(mEntryA1, 1000);
- mBubbleData.notificationEntryUpdated(mEntryA1);
-
- setPostTime(mEntryB1, 2000);
- mBubbleData.notificationEntryUpdated(mEntryB1);
-
- setPostTime(mEntryB2, 3000);
- setOngoing(mEntryB2, true);
- mBubbleData.notificationEntryUpdated(mEntryB2);
-
- setPostTime(mEntryA2, 4000);
- mBubbleData.notificationEntryUpdated(mEntryA2);
-
- // Then
- // New bubbles move to front, but stay behind any ongoing bubbles.
- // Does not break grouping. (A2 is inserted after B1, even though it's newer).
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleB2, mBubbleB1, mBubbleA2, mBubbleA1));
- }
-
- @Test
- public void test_collapsed_removeBubble() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- sendUpdatedEntryAtTime(mEntryB1, 2000);
- sendUpdatedEntryAtTime(mEntryB2, 3000);
- sendUpdatedEntryAtTime(mEntryA2, 4000);
-
- // When
- mBubbleData.notificationEntryRemoved(mEntryB2, BubbleController.DISMISS_USER_GESTURE);
-
- // Then
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA2, mBubbleA1, mBubbleB1));
- }
-
- @Test
- public void test_collapsed_updateBubble() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- sendUpdatedEntryAtTime(mEntryB1, 2000);
- sendUpdatedEntryAtTime(mEntryB2, 3000);
- sendUpdatedEntryAtTime(mEntryA2, 4000);
-
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1));
-
- // When
- sendUpdatedEntryAtTime(mEntryB2, 5000);
-
- // Then
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleB2, mBubbleB1, mBubbleA2, mBubbleA1));
- }
-
- @Test
- public void test_collapsed_updateBubble_withOngoing() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- setPostTime(mEntryA1, 1000);
- mBubbleData.notificationEntryUpdated(mEntryA1);
-
- setPostTime(mEntryB1, 2000);
- mBubbleData.notificationEntryUpdated(mEntryB1);
-
- setPostTime(mEntryB2, 3000);
- mBubbleData.notificationEntryUpdated(mEntryB2);
-
- setOngoing(mEntryA2, true);
- setPostTime(mEntryA2, 4000);
- mBubbleData.notificationEntryUpdated(mEntryA2);
-
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1));
-
- // When
- setPostTime(mEntryB1, 5000);
- mBubbleData.notificationEntryUpdated(mEntryB1);
-
- // Then
- // A2 remains in first position, due to being ongoing. B1 moves before B2, Group A
- // remains before group B.
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA2, mBubbleA1, mBubbleB1, mBubbleB2));
- }
-
- @Test
- public void test_collapse_afterUpdateWhileExpanded() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- sendUpdatedEntryAtTime(mEntryB1, 2000);
- sendUpdatedEntryAtTime(mEntryB2, 3000);
- sendUpdatedEntryAtTime(mEntryA2, 4000);
-
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1);
-
- changeExpandedStateAtTime(true, 5000L);
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1));
-
- sendUpdatedEntryAtTime(mEntryB1, 6000);
-
- // (No reordering while expanded)
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1));
-
- // When
- changeExpandedStateAtTime(false, 7000L);
-
- // Then
- // A1 moves to front on collapse, since it is the selected bubble (and most recently
- // accessed).
- // A2 moves next to A1 to maintain grouping.
- // B1 moves in front of B2, since it received an update while expanded
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA1, mBubbleA2, mBubbleB1, mBubbleB2));
- }
-
- @Test
- public void test_collapse_afterUpdateWhileExpanded_withOngoing() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- sendUpdatedEntryAtTime(mEntryB1, 2000);
-
- setOngoing(mEntryB2, true);
- sendUpdatedEntryAtTime(mEntryB2, 3000);
-
- sendUpdatedEntryAtTime(mEntryA2, 4000);
-
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1);
-
- changeExpandedStateAtTime(true, 5000L);
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleB2, mBubbleB1, mBubbleA2, mBubbleA1));
-
- sendUpdatedEntryAtTime(mEntryA1, 6000);
-
- // No reordering if expanded
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleB2, mBubbleB1, mBubbleA2, mBubbleA1));
-
- // When
- changeExpandedStateAtTime(false, 7000L);
-
- // Then
- // B2 remains in first position because it is ongoing.
- // B1 remains grouped with B2
- // A1 moves in front of A2, since it is more recently updated (and is selected).
- // B1 moves in front of B2, since it has more recent activity.
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleB2, mBubbleB1, mBubbleA1, mBubbleA2));
- }
-
- @Test
- public void test_collapsed_removeLastBubble_clearsSelectedBubble() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- sendUpdatedEntryAtTime(mEntryB1, 2000);
- sendUpdatedEntryAtTime(mEntryB2, 3000);
- sendUpdatedEntryAtTime(mEntryA2, 4000);
-
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1);
-
- mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
- mBubbleData.notificationEntryRemoved(mEntryB1, BubbleController.DISMISS_USER_GESTURE);
- mBubbleData.notificationEntryRemoved(mEntryB2, BubbleController.DISMISS_USER_GESTURE);
- mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_USER_GESTURE);
-
- assertThat(mBubbleData.getSelectedBubble()).isNull();
- }
-
- @Test
- public void test_expanded_addBubble_atMaxBubbles_expiresLeastActive() {
- // Given
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1);
-
- changeExpandedStateAtTime(true, 2000L);
- assertThat(mBubbleData.getSelectedBubble().getLastActivity()).isEqualTo(2000);
-
- sendUpdatedEntryAtTime(mEntryA2, 3000);
- sendUpdatedEntryAtTime(mEntryA3, 4000);
- sendUpdatedEntryAtTime(mEntryB1, 5000);
- sendUpdatedEntryAtTime(mEntryB2, 6000);
- sendUpdatedEntryAtTime(mEntryB3, 7000);
-
-
- // Then
- // A1 would be removed, but it is selected and expanded, so it should not go away.
- // Instead, fall through to removing A2 (the next oldest).
- assertThat(mBubbleData.getBubbles()).doesNotContain(mEntryA2);
- }
-
- @Test
- public void test_expanded_removeLastBubble_collapsesStack() {
- // Given
- setPostTime(mEntryA1, 1000);
- mBubbleData.notificationEntryUpdated(mEntryA1);
-
- setPostTime(mEntryB1, 2000);
- mBubbleData.notificationEntryUpdated(mEntryB1);
-
- setPostTime(mEntryB2, 3000);
- mBubbleData.notificationEntryUpdated(mEntryC1);
-
- mBubbleData.setExpanded(true);
-
- mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
- mBubbleData.notificationEntryRemoved(mEntryB1, BubbleController.DISMISS_USER_GESTURE);
- mBubbleData.notificationEntryRemoved(mEntryC1, BubbleController.DISMISS_USER_GESTURE);
-
- assertThat(mBubbleData.isExpanded()).isFalse();
- assertThat(mBubbleData.getSelectedBubble()).isNull();
- }
-
- // Bubbles do not reorder while expanded
- @Test
- public void test_expanded_selection_collapseToTop() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- sendUpdatedEntryAtTime(mEntryA2, 2000);
- sendUpdatedEntryAtTime(mEntryB1, 3000);
-
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleB1, mBubbleA2, mBubbleA1));
-
- changeExpandedStateAtTime(true, 4000L);
-
- // regrouping only happens when collapsed (after new or update) or expanded->collapsed
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleB1, mBubbleA2, mBubbleA1));
-
- changeExpandedStateAtTime(false, 6000L);
-
- // A1 is still selected and it's lastAccessed time has been updated
- // on collapse, sorting is applied, keeping the selected bubble at the front
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1);
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA1, mBubbleA2, mBubbleB1));
- }
-
- // New bubble from new app while stack is expanded
- @Test
- public void test_expanded_addBubble_newApp() {
- // Given
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- sendUpdatedEntryAtTime(mEntryA2, 2000);
- sendUpdatedEntryAtTime(mEntryA3, 3000);
- sendUpdatedEntryAtTime(mEntryB1, 4000);
- sendUpdatedEntryAtTime(mEntryB2, 5000);
-
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1);
-
- changeExpandedStateAtTime(true, 6000L);
-
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1);
- assertThat(mBubbleData.getSelectedBubble().getLastActivity()).isEqualTo(6000L);
-
- // regrouping only happens when collapsed (after new or update) or expanded->collapsed
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleB2, mBubbleB1, mBubbleA3, mBubbleA2, mBubbleA1));
-
- // When
- sendUpdatedEntryAtTime(mEntryC1, 7000);
-
- // Then
- // A2 is expired. A1 was oldest, but lastActivityTime is reset when expanded, since A1 is
- // selected.
- // C1 is added at the end since bubbles are expanded.
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleB2, mBubbleB1, mBubbleA3, mBubbleA1, mBubbleC1));
- }
-
- // New bubble from existing app while stack is expanded
- @Test
- public void test_expanded_addBubble_existingApp() {
- // Given
- sendUpdatedEntryAtTime(mEntryB1, 1000);
- sendUpdatedEntryAtTime(mEntryB2, 2000);
- sendUpdatedEntryAtTime(mEntryA1, 3000);
- sendUpdatedEntryAtTime(mEntryA2, 4000);
- sendUpdatedEntryAtTime(mEntryA3, 5000);
-
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleB1);
-
- changeExpandedStateAtTime(true, 6000L);
-
- // B1 is first (newest, since it's just been expanded and is selected)
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleB1);
- assertThat(mBubbleData.getSelectedBubble().getLastActivity()).isEqualTo(6000L);
-
- // regrouping only happens when collapsed (after new or update) or while collapsing
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA3, mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1));
-
- // When
- sendUpdatedEntryAtTime(mEntryB3, 7000);
-
- // Then
- // (B2 is expired, B1 was oldest, but it's lastActivityTime is updated at the point when
- // the stack was expanded, since it is the selected bubble.
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA3, mBubbleA2, mBubbleA1, mBubbleB3, mBubbleB1));
- }
-
- // Updated bubble from existing app while stack is expanded
- @Test
- public void test_expanded_updateBubble_existingApp() {
- sendUpdatedEntryAtTime(mEntryA1, 1000);
- sendUpdatedEntryAtTime(mEntryA2, 2000);
- sendUpdatedEntryAtTime(mEntryB1, 3000);
- sendUpdatedEntryAtTime(mEntryB2, 4000);
-
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleB2, mBubbleB1, mBubbleA2, mBubbleA1));
- mBubbleData.setExpanded(true);
-
- sendUpdatedEntryAtTime(mEntryA1, 5000);
-
- // Does not reorder while expanded (for an update).
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleB2, mBubbleB1, mBubbleA2, mBubbleA1));
- }
-
- @Test
- public void test_expanded_updateBubble() {
- // Given
- assertThat(mBubbleData.hasBubbles()).isFalse();
- assertThat(mBubbleData.isExpanded()).isFalse();
-
- setPostTime(mEntryA1, 1000);
- mBubbleData.notificationEntryUpdated(mEntryA1);
-
- setPostTime(mEntryB1, 2000);
- mBubbleData.notificationEntryUpdated(mEntryB1);
-
- setPostTime(mEntryB2, 3000);
- mBubbleData.notificationEntryUpdated(mEntryB2);
-
- setPostTime(mEntryA2, 4000);
- mBubbleData.notificationEntryUpdated(mEntryA2);
-
- mBubbleData.setExpanded(true);
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1));
-
- // When
- setPostTime(mEntryB1, 5000);
- mBubbleData.notificationEntryUpdated(mEntryB1);
-
- // Then
- // B1 remains in the same place due to being expanded
- assertThat(mBubbleData.getBubbles()).isEqualTo(
- ImmutableList.of(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1));
+ /** Syntactic sugar to keep assertions more readable */
+ private static <T> List<T> listOf(T... a) {
+ return ImmutableList.copyOf(a);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleFlyoutViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleFlyoutViewTest.java
new file mode 100644
index 0000000..173237f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleFlyoutViewTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.bubbles;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotSame;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.verify;
+
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class BubbleFlyoutViewTest extends SysuiTestCase {
+ private BubbleFlyoutView mFlyout;
+ private TextView mFlyoutText;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mFlyout = new BubbleFlyoutView(getContext());
+
+ mFlyoutText = mFlyout.findViewById(R.id.bubble_flyout_text);
+ }
+
+ @Test
+ public void testShowFlyout_isVisible() {
+ mFlyout.showFlyout("Hello", new PointF(100, 100), 500, true, Color.WHITE, null);
+ assertEquals("Hello", mFlyoutText.getText());
+ assertEquals(View.VISIBLE, mFlyout.getVisibility());
+ assertEquals(1f, mFlyoutText.getAlpha(), .01f);
+ }
+
+ @Test
+ public void testFlyoutHide_runsCallback() {
+ Runnable after = Mockito.mock(Runnable.class);
+ mFlyout.showFlyout("Hello", new PointF(100, 100), 500, true, Color.WHITE, after);
+ mFlyout.hideFlyout();
+
+ verify(after).run();
+ }
+
+ @Test
+ public void testSetCollapsePercent() {
+ mFlyout.showFlyout("Hello", new PointF(100, 100), 500, true, Color.WHITE, null);
+
+ float initialTranslationZ = mFlyout.getTranslationZ();
+
+ mFlyout.setCollapsePercent(1f);
+ assertEquals(0f, mFlyoutText.getAlpha(), 0.01f);
+ assertNotSame(0f, mFlyoutText.getTranslationX()); // Should have moved to collapse.
+ assertTrue(mFlyout.getTranslationZ() < initialTranslationZ); // Should be descending.
+
+ mFlyout.setCollapsePercent(0f);
+ assertEquals(1f, mFlyoutText.getAlpha(), 0.01f);
+ assertEquals(0f, mFlyoutText.getTranslationX());
+ assertEquals(initialTranslationZ, mFlyout.getTranslationZ());
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleStackViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleStackViewTest.java
deleted file mode 100644
index bafae6c..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleStackViewTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open 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.bubbles;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.widget.TextView;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class BubbleStackViewTest extends SysuiTestCase {
- private BubbleStackView mStackView;
- @Mock private Bubble mBubble;
- @Mock private NotificationEntry mNotifEntry;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mStackView = new BubbleStackView(mContext, new BubbleData(getContext()), null);
- mBubble.entry = mNotifEntry;
- }
-
- @Test
- public void testAnimateInFlyoutForBubble() {
- when(mNotifEntry.getUpdateMessage(any())).thenReturn("Test Flyout Message.");
- mStackView.animateInFlyoutForBubble(mBubble);
-
- assertEquals("Test Flyout Message.",
- ((TextView) mStackView.findViewById(R.id.bubble_flyout_text)).getText());
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
index cd84805..2990b3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -17,6 +17,8 @@
package com.android.systemui.bubbles.animation;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.mockito.Mockito.verify;
import android.content.res.Resources;
import android.graphics.Point;
@@ -31,6 +33,7 @@
import com.android.systemui.R;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
@@ -69,14 +72,14 @@
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
testBubblesInCorrectExpandedPositions();
- Mockito.verify(afterExpand).run();
+ verify(afterExpand).run();
Runnable afterCollapse = Mockito.mock(Runnable.class);
mExpandedController.collapseBackToStack(afterCollapse);
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
testStackedAtPosition(mExpansionPoint.x, mExpansionPoint.y, -1);
- Mockito.verify(afterExpand).run();
+ verify(afterExpand).run();
}
@Test
@@ -140,6 +143,79 @@
testBubblesInCorrectExpandedPositions();
}
+ @Test
+ public void testMagnetToDismiss_dismiss() throws InterruptedException {
+ expand();
+
+ final View draggedOutView = mViews.get(0);
+ final Runnable after = Mockito.mock(Runnable.class);
+
+ mExpandedController.prepareForBubbleDrag(draggedOutView);
+ mExpandedController.dragBubbleOut(draggedOutView, 25, 25);
+
+ // Magnet to dismiss, verify the bubble is at the dismiss target and the callback was
+ // called.
+ mExpandedController.magnetBubbleToDismiss(
+ mViews.get(0), 100 /* velX */, 100 /* velY */, 1000 /* destY */, after);
+ waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+ verify(after).run();
+ assertEquals(1000, mViews.get(0).getTranslationY(), .1f);
+
+ // Dismiss the now-magneted bubble, verify that the callback was called.
+ final Runnable afterDismiss = Mockito.mock(Runnable.class);
+ mExpandedController.dismissDraggedOutBubble(afterDismiss);
+ waitForPropertyAnimations(DynamicAnimation.ALPHA);
+ verify(after).run();
+
+ waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+
+ assertEquals(mBubblePadding, mViews.get(1).getTranslationX(), 1f);
+ }
+
+ @Test
+ @Ignore("Flaky")
+ public void testMagnetToDismiss_demagnetizeThenDrag() throws InterruptedException {
+ expand();
+
+ final View draggedOutView = mViews.get(0);
+ final Runnable after = Mockito.mock(Runnable.class);
+
+ mExpandedController.prepareForBubbleDrag(draggedOutView);
+ mExpandedController.dragBubbleOut(draggedOutView, 25, 25);
+
+ // Magnet to dismiss, verify the bubble is at the dismiss target and the callback was
+ // called.
+ mExpandedController.magnetBubbleToDismiss(
+ draggedOutView, 100 /* velX */, 100 /* velY */, 1000 /* destY */, after);
+ waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+ verify(after).run();
+ assertEquals(1000, mViews.get(0).getTranslationY(), .1f);
+
+ // Demagnetize the bubble towards (25, 25).
+ mExpandedController.demagnetizeBubbleTo(25 /* x */, 25 /* y */, 100, 100);
+
+ // Start dragging towards (20, 20).
+ mExpandedController.dragBubbleOut(draggedOutView, 20, 20);
+
+ // Since we just demagnetized, the bubble shouldn't be at (20, 20), it should be animating
+ // towards it.
+ assertNotEquals(20, draggedOutView.getTranslationX());
+ assertNotEquals(20, draggedOutView.getTranslationY());
+ waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+
+ // Waiting for the animations should result in the bubble ending at (20, 20) since the
+ // animation end value was updated.
+ assertEquals(20, draggedOutView.getTranslationX(), 1f);
+ assertEquals(20, draggedOutView.getTranslationY(), 1f);
+
+ // Drag to (30, 30).
+ mExpandedController.dragBubbleOut(draggedOutView, 30, 30);
+
+ // It should go there instantly since the animations finished.
+ assertEquals(30, draggedOutView.getTranslationX(), 1f);
+ assertEquals(30, draggedOutView.getTranslationY(), 1f);
+ }
+
/** Expand the stack and wait for animations to finish. */
private void expand() throws InterruptedException {
mExpandedController.expandFromStack(mExpansionPoint, Mockito.mock(Runnable.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
index 9fce092..a398fba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
@@ -195,9 +195,11 @@
@Override
protected void animateValueForChild(DynamicAnimation.ViewProperty property, View view,
- float value, float startVel, long startDelay, Runnable[] afterCallbacks) {
+ float value, float startVel, long startDelay, float stiffness,
+ float dampingRatio, Runnable[] afterCallbacks) {
mMainThreadHandler.post(() -> super.animateValueForChild(
- property, view, value, startVel, startDelay, afterCallbacks));
+ property, view, value, startVel, startDelay, stiffness, dampingRatio,
+ afterCallbacks));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
index 910cee3..b83276b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
@@ -17,6 +17,8 @@
package com.android.systemui.bubbles.animation;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.mockito.Mockito.verify;
import android.graphics.PointF;
import android.testing.AndroidTestingRunner;
@@ -33,6 +35,7 @@
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
import org.mockito.Spy;
@SmallTest
@@ -223,6 +226,59 @@
assertEquals(prevStackPos, mStackController.getStackPosition());
}
+ @Test
+ public void testMagnetToDismiss_dismiss() throws InterruptedException {
+ final Runnable after = Mockito.mock(Runnable.class);
+
+ // Magnet to dismiss, verify the stack is at the dismiss target and the callback was
+ // called.
+ mStackController.magnetToDismiss(100 /* velX */, 100 /* velY */, 1000 /* destY */, after);
+ waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+ verify(after).run();
+ assertEquals(1000, mViews.get(0).getTranslationY(), .1f);
+
+ // Dismiss the stack, verify that the callback was called.
+ final Runnable afterImplode = Mockito.mock(Runnable.class);
+ mStackController.implodeStack(afterImplode);
+ waitForPropertyAnimations(
+ DynamicAnimation.ALPHA, DynamicAnimation.SCALE_X, DynamicAnimation.SCALE_Y);
+ verify(after).run();
+ }
+
+ @Test
+ public void testMagnetToDismiss_demagnetizeThenDrag() throws InterruptedException {
+ final Runnable after = Mockito.mock(Runnable.class);
+
+ // Magnet to dismiss, verify the stack is at the dismiss target and the callback was
+ // called.
+ mStackController.magnetToDismiss(100 /* velX */, 100 /* velY */, 1000 /* destY */, after);
+ waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+ verify(after).run();
+
+ assertEquals(1000, mViews.get(0).getTranslationY(), .1f);
+
+ // Demagnetize towards (25, 25) and then send a touch event.
+ mStackController.demagnetizeFromDismissToPoint(25, 25, 0, 0);
+ waitForLayoutMessageQueue();
+ mStackController.moveStackFromTouch(20, 20);
+
+ // Since the stack is demagnetizing, it shouldn't be at the stack position yet.
+ assertNotEquals(20, mStackController.getStackPosition().x, 1f);
+ assertNotEquals(20, mStackController.getStackPosition().y, 1f);
+
+ waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+
+ // Once the animation is done it should end at the touch position coordinates.
+ assertEquals(20, mStackController.getStackPosition().x, 1f);
+ assertEquals(20, mStackController.getStackPosition().y, 1f);
+
+ mStackController.moveStackFromTouch(30, 30);
+
+ // Touches after the animation are done should change the stack position instantly.
+ assertEquals(30, mStackController.getStackPosition().x, 1f);
+ assertEquals(30, mStackController.getStackPosition().y, 1f);
+ }
+
/**
* Checks every child view to make sure it's stacked at the given coordinates, off to the left
* or right side depending on offset multiplier.
@@ -249,5 +305,13 @@
super.flingThenSpringFirstBubbleWithStackFollowing(
property, vel, friction, spring, finalPosition));
}
+
+ @Override
+ protected void springFirstBubbleWithStackFollowing(DynamicAnimation.ViewProperty property,
+ SpringForce spring, float vel, float finalPosition) {
+ mMainThreadHandler.post(() ->
+ super.springFirstBubbleWithStackFollowing(
+ property, spring, vel, finalPosition));
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
index df014a4..af2de1b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
@@ -73,8 +73,6 @@
doReturn(false).when(mConfig).alwaysOnEnabled(anyInt());
mDockManagerFake = spy(new DockManagerFake());
- mContext.putComponent(DockManager.class, mDockManagerFake);
-
mDockHandler = new DozeDockHandler(mContext, mMachine, mHost, mConfig,
Handler.createAsync(Looper.myLooper()), mDockManagerFake);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 1ac6bef..6979fd8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -38,7 +38,6 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerFake;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.wakelock.WakeLock;
@@ -84,7 +83,6 @@
mSensors = new FakeSensorManager(mContext);
mWakeLock = new WakeLockFake();
mDockManagerFake = spy(new DockManagerFake());
- mContext.putComponent(DockManager.class, mDockManagerFake);
mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, mConfig, mParameters,
mSensors, Handler.createAsync(Looper.myLooper()), mWakeLock, true,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index 161b409..4d95f3f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -46,15 +46,15 @@
import com.android.systemui.power.PowerUI.WarningsUI;
import com.android.systemui.statusbar.phone.StatusBar;
-import java.time.Duration;
-import java.util.concurrent.TimeUnit;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.time.Duration;
+import java.util.concurrent.TimeUnit;
+
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@SmallTest
@@ -78,8 +78,8 @@
private EnhancedEstimates mEnhancedEstimates;
@Mock private PowerManager mPowerManager;
@Mock private IThermalService mThermalServiceMock;
- private IThermalEventListener mThermalEventUsbListener;
- private IThermalEventListener mThermalEventSkinListener;
+ private IThermalEventListener mUsbThermalEventListener;
+ private IThermalEventListener mSkinThermalEventListener;
@Before
public void setup() {
@@ -91,8 +91,8 @@
mContext.addMockSystemService(Context.POWER_SERVICE, mPowerManager);
createPowerUi();
- mThermalEventSkinListener = mPowerUI.new ThermalEventSkinListener();
- mThermalEventUsbListener = mPowerUI.new ThermalEventUsbListener();
+ mSkinThermalEventListener = mPowerUI.new SkinThermalEventListener();
+ mUsbThermalEventListener = mPowerUI.new UsbThermalEventListener();
}
@Test
@@ -100,7 +100,7 @@
mPowerUI.start();
final Temperature temp = getCriticalStatusTemp(Temperature.TYPE_SKIN, "skin1");
- mThermalEventSkinListener.notifyThrottling(temp);
+ mSkinThermalEventListener.notifyThrottling(temp);
// dismiss skin high temperature warning when throttling status is critical
TestableLooper.get(this).processAllMessages();
@@ -113,7 +113,7 @@
mPowerUI.start();
final Temperature temp = getEmergencyStatusTemp(Temperature.TYPE_SKIN, "skin2");
- mThermalEventSkinListener.notifyThrottling(temp);
+ mSkinThermalEventListener.notifyThrottling(temp);
// show skin high temperature warning when throttling status is emergency
TestableLooper.get(this).processAllMessages();
@@ -126,7 +126,7 @@
mPowerUI.start();
final Temperature temp = getCriticalStatusTemp(Temperature.TYPE_USB_PORT, "usb1");
- mThermalEventUsbListener.notifyThrottling(temp);
+ mUsbThermalEventListener.notifyThrottling(temp);
// not show usb high temperature alarm when throttling status is critical
TestableLooper.get(this).processAllMessages();
@@ -138,7 +138,7 @@
mPowerUI.start();
final Temperature temp = getEmergencyStatusTemp(Temperature.TYPE_USB_PORT, "usb2");
- mThermalEventUsbListener.notifyThrottling(temp);
+ mUsbThermalEventListener.notifyThrottling(temp);
// show usb high temperature alarm when throttling status is emergency
TestableLooper.get(this).processAllMessages();
@@ -152,7 +152,6 @@
resources.addOverride(R.integer.config_showTemperatureWarning, 0);
mPowerUI.start();
- mPowerUI.registerThermalEventListener();
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
@@ -166,7 +165,6 @@
resources.addOverride(R.integer.config_showUsbPortAlarm, 0);
mPowerUI.start();
- mPowerUI.registerThermalEventListener();
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
@@ -174,6 +172,155 @@
}
@Test
+ public void testSettingOverrideConfig_disableSkinTemperatureWarning() throws Exception {
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 0);
+ TestableResources resources = mContext.getOrCreateTestableResources();
+ resources.addOverride(R.integer.config_showTemperatureWarning, 1);
+
+ mPowerUI.start();
+
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(0))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ }
+
+ @Test
+ public void testSettingOverrideConfig_disableUsbTemperatureAlarm() throws Exception {
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 0);
+ TestableResources resources = mContext.getOrCreateTestableResources();
+ resources.addOverride(R.integer.config_showUsbPortAlarm, 1);
+
+ mPowerUI.start();
+
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(0))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
+ }
+
+ @Test
+ public void testThermalEventListenerRegistration_success_skinType() throws Exception {
+ // Settings SHOW_TEMPERATURE_WARNING is set to 1
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 1);
+
+ // success registering skin thermal event listener
+ when(mThermalServiceMock.registerThermalEventListenerWithType(
+ anyObject(), eq(Temperature.TYPE_SKIN))).thenReturn(true);
+
+ mPowerUI.doSkinThermalEventListenerRegistration();
+
+ // verify registering skin thermal event listener, return true (success)
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(1))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+
+ // Settings SHOW_TEMPERATURE_WARNING is set to 0
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 0);
+
+ mPowerUI.doSkinThermalEventListenerRegistration();
+
+ // verify unregistering skin thermal event listener
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(anyObject());
+ }
+
+ @Test
+ public void testThermalEventListenerRegistration_fail_skinType() throws Exception {
+ // Settings SHOW_TEMPERATURE_WARNING is set to 1
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 1);
+
+ // fail registering skin thermal event listener
+ when(mThermalServiceMock.registerThermalEventListenerWithType(
+ anyObject(), eq(Temperature.TYPE_SKIN))).thenReturn(false);
+
+ mPowerUI.doSkinThermalEventListenerRegistration();
+
+ // verify registering skin thermal event listener, return false (fail)
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(1))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+
+ // Settings SHOW_TEMPERATURE_WARNING is set to 0
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 0);
+
+ mPowerUI.doSkinThermalEventListenerRegistration();
+
+ // verify that cannot unregister listener (current state is unregistered)
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(anyObject());
+
+ // Settings SHOW_TEMPERATURE_WARNING is set to 1
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 1);
+
+ mPowerUI.doSkinThermalEventListenerRegistration();
+
+ // verify that can register listener (current state is unregistered)
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(2))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ }
+
+ @Test
+ public void testThermalEventListenerRegistration_success_usbType() throws Exception {
+ // Settings SHOW_USB_TEMPERATURE_ALARM is set to 1
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 1);
+
+ // success registering usb thermal event listener
+ when(mThermalServiceMock.registerThermalEventListenerWithType(
+ anyObject(), eq(Temperature.TYPE_USB_PORT))).thenReturn(true);
+
+ mPowerUI.doUsbThermalEventListenerRegistration();
+
+ // verify registering usb thermal event listener, return true (success)
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(1))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
+
+ // Settings SHOW_USB_TEMPERATURE_ALARM is set to 0
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 0);
+
+ // verify unregistering usb thermal event listener
+ mPowerUI.doUsbThermalEventListenerRegistration();
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(anyObject());
+ }
+
+ @Test
+ public void testThermalEventListenerRegistration_fail_usbType() throws Exception {
+ // Settings SHOW_USB_TEMPERATURE_ALARM is set to 1
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 1);
+
+ // fail registering usb thermal event listener
+ when(mThermalServiceMock.registerThermalEventListenerWithType(
+ anyObject(), eq(Temperature.TYPE_USB_PORT))).thenReturn(false);
+
+ mPowerUI.doUsbThermalEventListenerRegistration();
+
+ // verify registering usb thermal event listener, return false (fail)
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(1))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
+
+ // Settings SHOW_USB_TEMPERATURE_ALARM is set to 0
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 0);
+
+ mPowerUI.doUsbThermalEventListenerRegistration();
+
+ // verify that cannot unregister listener (current state is unregistered)
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(anyObject());
+
+ // Settings SHOW_USB_TEMPERATURE_ALARM is set to 1
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 1);
+
+ mPowerUI.doUsbThermalEventListenerRegistration();
+
+ // verify that can register listener (current state is unregistered)
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(2)).registerThermalEventListenerWithType(
+ anyObject(), eq(Temperature.TYPE_USB_PORT));
+ }
+
+ @Test
public void testMaybeShowHybridWarning() {
mPowerUI.start();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 183e027..d18cebb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -19,6 +19,7 @@
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.os.Handler;
@@ -88,7 +89,7 @@
assertEquals(NUM_FAKES, mManagers.size());
for (int i = 0; i < NUM_FAKES; i++) {
- Mockito.when(mManagers.get(i).getBindPriority()).thenReturn(i);
+ when(mManagers.get(i).getBindPriority()).thenReturn(i);
}
mTileService.recalculateBindAllowance();
for (int i = 0; i < NUM_FAKES; i++) {
@@ -145,6 +146,7 @@
protected TileServiceManager onCreateTileService(ComponentName component, Tile qsTile) {
TileServiceManager manager = mock(TileServiceManager.class);
mManagers.add(manager);
+ when(manager.isLifecycleStarted()).thenReturn(true);
return manager;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 2bde5f6..b049632 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -128,20 +128,6 @@
}
@Test
- public void testTopAppWindowChanged() {
- mCommandQueue.topAppWindowChanged(DEFAULT_DISPLAY, true);
- waitForIdleSync();
- verify(mCallbacks).topAppWindowChanged(eq(DEFAULT_DISPLAY), eq(true));
- }
-
- @Test
- public void testTopAppWindowChangedForSecondaryDisplay() {
- mCommandQueue.topAppWindowChanged(SECONDARY_DISPLAY, true);
- waitForIdleSync();
- verify(mCallbacks).topAppWindowChanged(eq(SECONDARY_DISPLAY), eq(true));
- }
-
- @Test
public void testShowImeButton() {
mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, 1, 2, true);
waitForIdleSync();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 2858ba9..6d9a77c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -257,7 +257,7 @@
when(mAccessibilityController.isAccessibilityEnabled()).thenReturn(true);
clickCaptor.getValue().onClick(mLockIcon);
- verify(mShadeController).showBouncer(eq(false));
+ verify(mShadeController).animateCollapsePanels(anyInt(), eq(true));
longClickCaptor.getValue().onLongClick(mLockIcon);
verify(mLockPatternUtils).requireCredentialEntry(anyInt());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
index 1a1acdf..0800cb9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
@@ -17,6 +17,8 @@
package com.android.systemui.statusbar;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -99,7 +101,7 @@
public void testNotificationRemovalCallsRemoveNotification() {
mListener.onNotificationRemoved(mSbn, mRanking);
TestableLooper.get(this).processAllMessages();
- verify(mEntryManager).removeNotification(mSbn.getKey(), mRanking);
+ verify(mEntryManager).removeNotification(eq(mSbn.getKey()), eq(mRanking), anyInt());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/MediaNotificationProcessorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/MediaNotificationProcessorTest.java
index b03abec..7eeae67 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/MediaNotificationProcessorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/MediaNotificationProcessorTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertNotSame;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -24,17 +26,22 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
+import android.annotation.Nullable;
import android.app.Notification;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.test.suitebuilder.annotation.SmallTest;
import android.widget.RemoteViews;
+import androidx.palette.graphics.Palette;
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -43,9 +50,18 @@
@RunWith(AndroidJUnit4.class)
public class MediaNotificationProcessorTest extends SysuiTestCase {
+ private static final int BITMAP_WIDTH = 10;
+ private static final int BITMAP_HEIGHT = 10;
+
+ /**
+ * Color tolerance is borrowed from the AndroidX test utilities for Palette.
+ */
+ private static final int COLOR_TOLERANCE = 8;
+
private MediaNotificationProcessor mProcessor;
private Bitmap mBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
private ImageGradientColorizer mColorizer;
+ @Nullable private Bitmap mArtwork;
@Before
public void setUp() {
@@ -53,6 +69,14 @@
mProcessor = new MediaNotificationProcessor(getContext(), getContext(), mColorizer);
}
+ @After
+ public void tearDown() {
+ if (mArtwork != null) {
+ mArtwork.recycle();
+ mArtwork = null;
+ }
+ }
+
@Test
public void testColorizedWithLargeIcon() {
Notification.Builder builder = new Notification.Builder(getContext()).setSmallIcon(
@@ -100,6 +124,36 @@
assertNotSame(contentView, remoteViews);
}
+ @Test
+ public void findBackgroundSwatch_white() {
+ // Given artwork that is completely white.
+ mArtwork = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(mArtwork);
+ canvas.drawColor(Color.WHITE);
+ // WHEN the background swatch is computed
+ Palette.Swatch swatch = MediaNotificationProcessor.findBackgroundSwatch(mArtwork);
+ // THEN the swatch color is white
+ assertCloseColors(swatch.getRgb(), Color.WHITE);
+ }
+
+ @Test
+ public void findBackgroundSwatch_red() {
+ // Given artwork that is completely red.
+ mArtwork = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(mArtwork);
+ canvas.drawColor(Color.RED);
+ // WHEN the background swatch is computed
+ Palette.Swatch swatch = MediaNotificationProcessor.findBackgroundSwatch(mArtwork);
+ // THEN the swatch color is red
+ assertCloseColors(swatch.getRgb(), Color.RED);
+ }
+
+ static void assertCloseColors(int expected, int actual) {
+ assertThat((float) Color.red(expected)).isWithin(COLOR_TOLERANCE).of(Color.red(actual));
+ assertThat((float) Color.green(expected)).isWithin(COLOR_TOLERANCE).of(Color.green(actual));
+ assertThat((float) Color.blue(expected)).isWithin(COLOR_TOLERANCE).of(Color.blue(actual));
+ }
+
public static class TestableColorizer extends ImageGradientColorizer {
private final Bitmap mBitmap;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index c8005dd..4d593c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -16,13 +16,20 @@
package com.android.systemui.statusbar.notification;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL;
+
+import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
+
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
@@ -51,6 +58,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.InitController;
@@ -61,6 +69,7 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.StatusBarIconView;
@@ -105,6 +114,7 @@
@Mock private ExpandableNotificationRow mRow;
@Mock private NotificationListContainer mListContainer;
@Mock private NotificationEntryListener mEntryListener;
+ @Mock private NotificationRemoveInterceptor mRemoveInterceptor;
@Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
@Mock private HeadsUpManager mHeadsUpManager;
@Mock private NotificationListenerService.RankingMap mRankingMap;
@@ -234,6 +244,7 @@
Dependency.get(InitController.class).executePostInitTasks();
mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mHeadsUpManager);
mEntryManager.addNotificationEntryListener(mEntryListener);
+ mEntryManager.setNotificationRemoveInterceptor(mRemoveInterceptor);
NotificationRowBinderImpl notificationRowBinder =
new NotificationRowBinderImpl(mContext, true /* allowLongPress */);
@@ -341,7 +352,7 @@
mEntry.setRow(mRow);
mEntryManager.getNotificationData().add(mEntry);
- mEntryManager.removeNotification(mSbn.getKey(), mRankingMap);
+ mEntryManager.removeNotification(mSbn.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
verify(mEntryListener, never()).onInflationError(any(), any());
@@ -357,7 +368,7 @@
public void testRemoveNotification_onEntryRemoveNotFiredIfEntryDoesntExist() {
com.android.systemui.util.Assert.isNotMainThread();
- mEntryManager.removeNotification("not_a_real_key", mRankingMap);
+ mEntryManager.removeNotification("not_a_real_key", mRankingMap, UNDEFINED_DISMISS_REASON);
verify(mEntryListener, never()).onEntryRemoved(
eq(mEntry), any(), eq(false) /* removedByUser */);
@@ -370,7 +381,7 @@
mEntryManager.setRowBinder(mMockedRowBinder);
mEntryManager.addNotification(mSbn, mRankingMap);
- mEntryManager.removeNotification(mSbn.getKey(), mRankingMap);
+ mEntryManager.removeNotification(mSbn.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
verify(mEntryListener, never()).onEntryRemoved(
eq(mEntry), any(), eq(false /* removedByUser */));
@@ -449,7 +460,7 @@
mEntryManager.addNotificationLifetimeExtender(extender);
// WHEN the notification is removed
- mEntryManager.removeNotification(mEntry.key, mRankingMap);
+ mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
// THEN the extender is asked to manage the lifetime
verify(extender).setShouldManageLifetime(mEntry, true);
@@ -465,7 +476,7 @@
mEntryManager.getNotificationData().add(mEntry);
final FakeNotificationLifetimeExtender extender = new FakeNotificationLifetimeExtender();
mEntryManager.addNotificationLifetimeExtender(extender);
- mEntryManager.removeNotification(mEntry.key, mRankingMap);
+ mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
assertTrue(extender.isManaging(mEntry.key));
// WHEN the extender finishes its extension
@@ -485,7 +496,7 @@
NotificationLifetimeExtender extender = mock(NotificationLifetimeExtender.class);
when(extender.shouldExtendLifetime(mEntry)).thenReturn(true);
mEntryManager.addNotificationLifetimeExtender(extender);
- mEntryManager.removeNotification(mEntry.key, mRankingMap);
+ mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
// WHEN the notification is updated
mEntryManager.updateNotification(mEntry.notification, mRankingMap);
@@ -510,13 +521,13 @@
mEntryManager.addNotificationLifetimeExtender(extender2);
// GIVEN a notification was lifetime-extended and extender2 is managing it
- mEntryManager.removeNotification(mEntry.key, mRankingMap);
+ mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
verify(extender1, never()).setShouldManageLifetime(mEntry, true);
verify(extender2).setShouldManageLifetime(mEntry, true);
// WHEN the extender1 changes its mind and wants to extend the lifetime of the notif
when(extender1.shouldExtendLifetime(mEntry)).thenReturn(true);
- mEntryManager.removeNotification(mEntry.key, mRankingMap);
+ mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
// THEN extender2 stops managing the notif and extender1 starts managing it
verify(extender1).setShouldManageLifetime(mEntry, true);
@@ -530,7 +541,45 @@
@Test
public void testPerformRemoveNotification_removedEntry() {
mEntryManager.getNotificationData().remove(mSbn.getKey(), null /* ranking */);
- mEntryManager.performRemoveNotification(mSbn);
+ mEntryManager.performRemoveNotification(mSbn, REASON_CANCEL);
+ }
+
+ @Test
+ public void testRemoveInterceptor_interceptsDontGetRemoved() {
+ // GIVEN an entry manager with a notification
+ mEntryManager.setRowBinder(mMockedRowBinder);
+ mEntryManager.getNotificationData().add(mEntry);
+
+ // GIVEN interceptor that intercepts that entry
+ when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.key), anyInt()))
+ .thenReturn(true);
+
+ // WHEN the notification is removed
+ mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+
+ // THEN the interceptor intercepts & the entry is not removed & no listeners are called
+ assertNotNull(mEntryManager.getNotificationData().get(mEntry.key));
+ verify(mEntryListener, never()).onEntryRemoved(eq(mEntry),
+ any(NotificationVisibility.class), anyBoolean());
+ }
+
+ @Test
+ public void testRemoveInterceptor_notInterceptedGetsRemoved() {
+ // GIVEN an entry manager with a notification
+ mEntryManager.setRowBinder(mMockedRowBinder);
+ mEntryManager.getNotificationData().add(mEntry);
+
+ // GIVEN interceptor that doesn't intercept
+ when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.key), anyInt()))
+ .thenReturn(false);
+
+ // WHEN the notification is removed
+ mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+
+ // THEN the interceptor intercepts & the entry is not removed & no listeners are called
+ assertNull(mEntryManager.getNotificationData().get(mEntry.key));
+ verify(mEntryListener, atLeastOnce()).onEntryRemoved(eq(mEntry),
+ any(NotificationVisibility.class), anyBoolean());
}
private Notification.Action createAction() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt
new file mode 100644
index 0000000..7632630
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.notification.row
+
+import android.app.INotificationManager
+import android.app.NotificationChannel
+import android.app.NotificationChannelGroup
+import android.app.NotificationManager.IMPORTANCE_DEFAULT
+import android.app.NotificationManager.IMPORTANCE_NONE
+import android.content.pm.ParceledListSlice
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME
+import androidx.test.filters.SmallTest
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+
+import com.android.systemui.SysuiTestCase
+
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.runner.RunWith
+import org.junit.Test
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class ChannelEditorDialogControllerTest : SysuiTestCase() {
+
+ private lateinit var controller: ChannelEditorDialogController
+ private lateinit var channel1: NotificationChannel
+ private lateinit var channel2: NotificationChannel
+ private lateinit var channelDefault: NotificationChannel
+ private lateinit var group: NotificationChannelGroup
+
+ private val appIcon = ColorDrawable(Color.MAGENTA)
+
+ @Mock
+ private lateinit var mockNoMan: INotificationManager
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ controller = ChannelEditorDialogController(mContext, mockNoMan)
+
+ channel1 = NotificationChannel(TEST_CHANNEL, TEST_CHANNEL_NAME, IMPORTANCE_DEFAULT)
+ channel2 = NotificationChannel(TEST_CHANNEL2, TEST_CHANNEL_NAME2, IMPORTANCE_DEFAULT)
+ channelDefault = NotificationChannel(
+ NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME, IMPORTANCE_DEFAULT)
+
+ group = NotificationChannelGroup(TEST_GROUP_ID, TEST_GROUP_NAME)
+
+ `when`(mockNoMan.getNotificationChannelGroupsForPackage(
+ eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean()))
+ .thenReturn(ParceledListSlice(listOf(group)))
+
+ `when`(mockNoMan.areNotificationsEnabledForPackage(eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
+ .thenReturn(true)
+ }
+
+ @Test
+ fun testPrepareDialogForApp_noExtraChannels() {
+ group.channels = listOf(channel1, channel2)
+ controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
+ setOf(channel1, channel2), appIcon, clickListener)
+
+ assertEquals(2, controller.providedChannels.size)
+ }
+
+ @Test
+ fun testPrepareDialogForApp_onlyDefaultChannel() {
+ group.addChannel(channelDefault)
+
+ controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
+ setOf(channelDefault), appIcon, clickListener)
+
+ assertEquals("No channels should be shown when there is only the miscellaneous channel",
+ 0, controller.providedChannels.size)
+ }
+
+ @Test
+ fun testPrepareDialogForApp_noProvidedChannels_noException() {
+ group.channels = listOf()
+
+ controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
+ setOf(), appIcon, clickListener)
+ }
+
+ @Test
+ fun testPrepareDialogForApp_retrievesUpto4Channels() {
+ val channel3 = NotificationChannel("test_channel_3", "Test channel 3", IMPORTANCE_DEFAULT)
+ val channel4 = NotificationChannel("test_channel_4", "Test channel 4", IMPORTANCE_DEFAULT)
+
+ group.channels = listOf(channel1, channel2, channel3, channel4)
+
+ controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
+ setOf(channel1), appIcon, clickListener)
+
+ assertEquals("ChannelEditorDialog should fetch enough channels to show 4",
+ 4, controller.providedChannels.size)
+ }
+
+ @Test
+ fun testApply_demoteChannel() {
+ group.channels = listOf(channel1, channel2)
+ controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
+ setOf(channel1, channel2), appIcon, clickListener)
+
+ // propose an adjustment of channel1
+ controller.proposeEditForChannel(channel1, IMPORTANCE_NONE)
+
+ controller.apply()
+
+ assertEquals("Proposed edits should take effect after apply",
+ IMPORTANCE_NONE, channel1.importance)
+
+ // Channel 2 shouldn't have changed
+ assertEquals("Proposed edits should take effect after apply",
+ IMPORTANCE_DEFAULT, channel2.importance)
+ }
+
+ @Test
+ fun testApply_demoteApp() {
+ group.channels = listOf(channel1, channel2)
+ controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
+ setOf(channel1, channel2), appIcon, clickListener)
+
+ controller.appNotificationsEnabled = false
+ controller.apply()
+
+ verify(mockNoMan, times(1)).setNotificationsEnabledForPackage(
+ eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(false))
+ }
+
+ @Test
+ fun testApply_promoteApp() {
+ // App starts out disabled
+ `when`(mockNoMan.areNotificationsEnabledForPackage(eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
+ .thenReturn(false)
+
+ controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
+ setOf(channel1, channel2), appIcon, clickListener)
+ controller.appNotificationsEnabled = true
+ controller.apply()
+
+ verify(mockNoMan, times(1)).setNotificationsEnabledForPackage(
+ eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(true))
+ }
+
+ private val clickListener = object : NotificationInfo.OnSettingsClickListener {
+ override fun onClick(v: View, c: NotificationChannel, appUid: Int) {
+ }
+ }
+
+ companion object {
+ const val TEST_APP_NAME = "Test App Name"
+ const val TEST_PACKAGE_NAME = "test_package"
+ const val TEST_SYSTEM_PACKAGE_NAME = PRINT_SPOOLER_PACKAGE_NAME
+ const val TEST_UID = 1
+ const val MULTIPLE_CHANNEL_COUNT = 2
+ const val TEST_CHANNEL = "test_channel"
+ const val TEST_CHANNEL_NAME = "Test Channel Name"
+ const val TEST_CHANNEL2 = "test_channel2"
+ const val TEST_CHANNEL_NAME2 = "Test Channel Name2"
+ const val TEST_GROUP_ID = "test_group_id"
+ const val TEST_GROUP_NAME = "Test Group Name"
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 5f0839d..6376bd3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -31,6 +31,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -317,7 +318,7 @@
any(INotificationManager.class),
eq(statusBarNotification.getPackageName()),
any(NotificationChannel.class),
- anyInt(),
+ anySet(),
eq(statusBarNotification),
any(NotificationInfo.CheckSaveListener.class),
any(NotificationInfo.OnSettingsClickListener.class),
@@ -345,7 +346,7 @@
any(INotificationManager.class),
eq(statusBarNotification.getPackageName()),
any(NotificationChannel.class),
- anyInt(),
+ anySet(),
eq(statusBarNotification),
any(NotificationInfo.CheckSaveListener.class),
any(NotificationInfo.OnSettingsClickListener.class),
@@ -375,7 +376,7 @@
any(INotificationManager.class),
eq(statusBarNotification.getPackageName()),
any(NotificationChannel.class),
- anyInt(),
+ anySet(),
eq(statusBarNotification),
any(NotificationInfo.CheckSaveListener.class),
any(NotificationInfo.OnSettingsClickListener.class),
@@ -404,7 +405,7 @@
any(INotificationManager.class),
eq(statusBarNotification.getPackageName()),
any(NotificationChannel.class),
- anyInt(),
+ anySet(),
eq(statusBarNotification),
any(NotificationInfo.CheckSaveListener.class),
any(NotificationInfo.OnSettingsClickListener.class),
@@ -432,7 +433,7 @@
any(INotificationManager.class),
eq(statusBarNotification.getPackageName()),
any(NotificationChannel.class),
- anyInt(),
+ anySet(),
eq(statusBarNotification),
any(NotificationInfo.CheckSaveListener.class),
any(NotificationInfo.OnSettingsClickListener.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 7bd2580..06acc73 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -20,7 +20,6 @@
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
@@ -54,7 +53,6 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
-import android.metrics.LogMaker;
import android.os.IBinder;
import android.os.UserHandle;
import android.provider.Settings;
@@ -70,7 +68,6 @@
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -86,6 +83,8 @@
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.util.HashSet;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
@SmallTest
@@ -103,6 +102,8 @@
private NotificationInfo mNotificationInfo;
private NotificationChannel mNotificationChannel;
private NotificationChannel mDefaultNotificationChannel;
+ private Set<NotificationChannel> mNotificationChannelSet = new HashSet<>();
+ private Set<NotificationChannel> mDefaultNotificationChannelSet = new HashSet<>();
private StatusBarNotification mSbn;
@Rule
@@ -153,9 +154,11 @@
// Some test channels.
mNotificationChannel = new NotificationChannel(
TEST_CHANNEL, TEST_CHANNEL_NAME, IMPORTANCE_LOW);
+ mNotificationChannelSet.add(mNotificationChannel);
mDefaultNotificationChannel = new NotificationChannel(
NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
IMPORTANCE_LOW);
+ mDefaultNotificationChannelSet.add(mDefaultNotificationChannel);
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
new Notification(), UserHandle.CURRENT, null, 0);
@@ -191,7 +194,7 @@
public void testBindNotification_SetsTextApplicationName() throws Exception {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn,
null, null, null,
true, false,
IMPORTANCE_DEFAULT, true);
@@ -206,7 +209,8 @@
when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
.thenReturn(iconDrawable);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn,
+ null, null, null, true, false,
IMPORTANCE_DEFAULT, true);
final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
assertEquals(iconDrawable, iconView.getDrawable());
@@ -215,7 +219,8 @@
@Test
public void testBindNotification_noDelegate() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn,
+ null, null, null, true, false,
IMPORTANCE_DEFAULT, true);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
assertEquals(GONE, nameView.getVisibility());
@@ -234,7 +239,8 @@
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("Other");
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_DEFAULT, true);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
assertEquals(VISIBLE, nameView.getVisibility());
@@ -246,7 +252,8 @@
@Test
public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_DEFAULT, true);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(GONE, groupNameView.getVisibility());
@@ -261,7 +268,8 @@
eq("test_group_id"), eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
.thenReturn(notificationChannelGroup);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_DEFAULT, true);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(View.VISIBLE, groupNameView.getVisibility());
@@ -271,7 +279,8 @@
@Test
public void testBindNotification_SetsTextChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_DEFAULT, true);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(TEST_CHANNEL_NAME, textView.getText());
@@ -280,8 +289,8 @@
@Test
public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
- false, IMPORTANCE_DEFAULT, true);
+ TEST_PACKAGE_NAME, mDefaultNotificationChannel, mDefaultNotificationChannelSet,
+ mSbn, null, null, null, true, false, IMPORTANCE_DEFAULT, true);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, textView.getVisibility());
}
@@ -293,7 +302,8 @@
when(mMockINotificationManager.getNumNotificationChannelsForPackage(
eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
+ TEST_PACKAGE_NAME, mDefaultNotificationChannel, mDefaultNotificationChannelSet,
+ mSbn, null, null, null, true,
false, IMPORTANCE_DEFAULT, true);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
@@ -302,7 +312,8 @@
@Test
public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, true,
IMPORTANCE_DEFAULT, true);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
@@ -311,7 +322,7 @@
@Test
public void testBindNotification_BlockLink_BlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, mock(
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, mock(
NotificationInfo.OnSettingsClickListener.class), null, true, false,
true /* isBlockingHelper */, IMPORTANCE_DEFAULT, true);
final View block =
@@ -326,7 +337,7 @@
public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
latch.countDown();
@@ -341,7 +352,8 @@
@Test
public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_DEFAULT, true);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
@@ -351,7 +363,7 @@
public void testBindNotification_SettingsButtonInvisibleWhenDeviceUnprovisioned()
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
}, null, false, false, IMPORTANCE_DEFAULT, true);
@@ -362,10 +374,11 @@
@Test
public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_DEFAULT, true);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
}, null, true, false, IMPORTANCE_DEFAULT, true);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
@@ -375,7 +388,7 @@
@Test
public void testBindNotificationLogging_notBlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn,
null, null, null,
true, false,
IMPORTANCE_DEFAULT, true);
@@ -389,7 +402,7 @@
@Test
public void testBindNotificationLogging_BlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn,
null, null, null,
false, true,
true,
@@ -404,7 +417,7 @@
@Test
public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn,
null, null, null,
false, true,
true,
@@ -417,7 +430,8 @@
public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null,
+ TEST_PACKAGE_NAME, mNotificationChannel,
+ createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT), mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(null, c);
latch.countDown();
@@ -433,7 +447,8 @@
public void testBindNotification_ChannelNameInvisibleWhenBundleFromDifferentChannels()
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
+ TEST_PACKAGE_NAME, mNotificationChannel,
+ createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT), mSbn, null, null,
null, true, false, IMPORTANCE_DEFAULT, true);
final TextView channelNameView =
mNotificationInfo.findViewById(R.id.channel_name);
@@ -444,7 +459,8 @@
@UiThreadTest
public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
+ TEST_PACKAGE_NAME, mNotificationChannel,
+ createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT), mSbn, null, null,
null, true, false, IMPORTANCE_DEFAULT, true);
assertEquals(GONE, mNotificationInfo.findViewById(
R.id.interruptiveness_settings).getVisibility());
@@ -455,7 +471,8 @@
@Test
public void testBindNotification_whenAppUnblockable() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, true,
IMPORTANCE_DEFAULT, true);
final TextView view = mNotificationInfo.findViewById(R.id.non_configurable_text);
assertEquals(View.VISIBLE, view.getVisibility());
@@ -468,7 +485,8 @@
@Test
public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_DEFAULT, true);
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
@@ -479,7 +497,8 @@
public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_LOW, false);
mNotificationInfo.findViewById(R.id.alert).performClick();
@@ -493,7 +512,8 @@
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_DEFAULT, true);
mNotificationInfo.findViewById(R.id.silence).performClick();
@@ -507,7 +527,8 @@
throws Exception {
int originalImportance = mNotificationChannel.getImportance();
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_DEFAULT, true);
mNotificationInfo.handleCloseControls(true, false);
@@ -522,7 +543,8 @@
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_UNSPECIFIED, true);
mNotificationInfo.handleCloseControls(true, false);
@@ -541,7 +563,8 @@
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
- 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
+ createMultipleChannelSet(10) /* numUniqueChannelsInRow */, mSbn,
+ listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */, true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
IMPORTANCE_DEFAULT, true);
@@ -570,7 +593,8 @@
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
- 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
+ createMultipleChannelSet(10) /* numUniqueChannelsInRow */, mSbn,
+ listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */,
false /* isNonblockable */, true /* isForBlockingHelper */,
true, IMPORTANCE_DEFAULT, true);
@@ -589,7 +613,8 @@
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
- 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
+ createMultipleChannelSet(10) /* numUniqueChannelsInRow */, mSbn,
+ listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */,
true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
@@ -608,7 +633,7 @@
mMockINotificationManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
- 1 /* numChannels */,
+ mNotificationChannelSet /* numChannels */,
mSbn,
null /* checkSaveListener */,
null /* onSettingsClick */,
@@ -635,7 +660,7 @@
mMockINotificationManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
- 1 /* numChannels */,
+ mNotificationChannelSet /* numChannels */,
mSbn,
null /* checkSaveListener */,
null /* onSettingsClick */,
@@ -664,7 +689,8 @@
public void testKeepUpdatesNotificationChannel_blockingHelper() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, true,
IMPORTANCE_LOW, false);
mNotificationInfo.findViewById(R.id.keep_showing).performClick();
@@ -683,7 +709,8 @@
public void testNoActionsUpdatesNotificationChannel_blockingHelper() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, true,
IMPORTANCE_DEFAULT, true);
mNotificationInfo.handleCloseControls(true, false);
@@ -701,7 +728,8 @@
public void testSilenceCallsUpdateNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_DEFAULT, true);
mNotificationInfo.findViewById(R.id.silence).performClick();
@@ -722,7 +750,8 @@
public void testUnSilenceCallsUpdateNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_LOW, false);
mNotificationInfo.findViewById(R.id.alert).performClick();
@@ -744,7 +773,8 @@
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_UNSPECIFIED, true);
mNotificationInfo.findViewById(R.id.silence).performClick();
@@ -766,7 +796,8 @@
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_MIN);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_MIN, false);
assertEquals(mContext.getString(R.string.inline_done_button),
@@ -782,7 +813,7 @@
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), updated.capture());
- assertTrue((updated.getValue().getUserLockedFields()& USER_LOCKED_IMPORTANCE) != 0);
+ assertTrue((updated.getValue().getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0);
assertEquals(IMPORTANCE_MIN, updated.getValue().getImportance());
}
@@ -791,7 +822,8 @@
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_MIN);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_MIN, false);
assertEquals(mContext.getString(R.string.inline_done_button),
@@ -807,7 +839,7 @@
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), updated.capture());
- assertTrue((updated.getValue().getUserLockedFields()& USER_LOCKED_IMPORTANCE) != 0);
+ assertTrue((updated.getValue().getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0);
assertEquals(IMPORTANCE_DEFAULT, updated.getValue().getImportance());
}
@@ -816,7 +848,8 @@
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_LOW, false);
assertEquals(mContext.getString(R.string.inline_done_button),
@@ -834,7 +867,8 @@
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_LOW, false);
mNotificationInfo.findViewById(R.id.alert).performClick();
@@ -855,7 +889,8 @@
public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn, null, null,
+ null, true, false,
IMPORTANCE_LOW, false);
mNotificationInfo.findViewById(R.id.alert).performClick();
@@ -871,7 +906,7 @@
public void testCloseControlsUpdatesWhenCheckSaveListenerUsesCallback() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
}, null, null, true, false, IMPORTANCE_LOW, false
@@ -894,7 +929,7 @@
public void testCloseControls_withoutHittingApply() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
}, null, null, true, false, IMPORTANCE_LOW, false
@@ -910,7 +945,7 @@
assertFalse(mNotificationInfo.willBeRemoved());
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+ TEST_PACKAGE_NAME, mNotificationChannel, mNotificationChannelSet, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
}, null, null, true, false, IMPORTANCE_LOW, false
@@ -918,4 +953,21 @@
assertFalse(mNotificationInfo.willBeRemoved());
}
+
+ private Set<NotificationChannel> createMultipleChannelSet(int howMany) {
+ Set<NotificationChannel> multiChannelSet = new HashSet<>();
+ for (int i = 0; i < howMany; i++) {
+ if (i == 0) {
+ multiChannelSet.add(mNotificationChannel);
+ continue;
+ }
+
+ NotificationChannel channel = new NotificationChannel(
+ TEST_CHANNEL, TEST_CHANNEL_NAME + i, IMPORTANCE_LOW);
+
+ multiChannelSet.add(channel);
+ }
+
+ return multiChannelSet;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
new file mode 100644
index 0000000..67c4a92
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.notification.stack;
+
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.ActivityStarterDelegate;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotificationSectionsManagerTest extends SysuiTestCase {
+
+ @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule();
+
+ @Mock private NotificationStackScrollLayout mNssl;
+ @Mock private ActivityStarterDelegate mActivityStarterDelegate;
+
+ private NotificationSectionsManager mSectionsManager;
+
+ @Before
+ public void setUp() {
+ mSectionsManager = new NotificationSectionsManager(mNssl, mActivityStarterDelegate, true);
+ // Required in order for the header inflation to work properly
+ when(mNssl.generateLayoutParams(any(AttributeSet.class)))
+ .thenReturn(new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
+ mSectionsManager.inflateViews(mContext);
+ when(mNssl.indexOfChild(any(View.class))).thenReturn(-1);
+ }
+
+ @Test
+ public void testInsertHeader() {
+ // GIVEN a stack with HI and LO rows but no section headers
+ setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HIPRI, ChildType.LOPRI);
+
+ // WHEN we update the section headers
+ mSectionsManager.updateSectionBoundaries();
+
+ // THEN a LO section header is added
+ verify(mNssl).addView(mSectionsManager.getGentleHeaderView(), 3);
+ }
+
+ @Test
+ public void testRemoveHeader() {
+ // GIVEN a stack that originally had a header between the HI and LO sections
+ setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.LOPRI);
+ mSectionsManager.updateSectionBoundaries();
+
+ // WHEN the last LO row is replaced with a HI row
+ setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HEADER, ChildType.HIPRI);
+ clearInvocations(mNssl);
+ mSectionsManager.updateSectionBoundaries();
+
+ // THEN the LO section header is removed
+ verify(mNssl).removeView(mSectionsManager.getGentleHeaderView());
+ }
+
+ @Test
+ public void testDoNothingIfHeaderAlreadyRemoved() {
+ // GIVEN a stack with only HI rows
+ setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HIPRI);
+
+ // WHEN we update the sections headers
+ mSectionsManager.updateSectionBoundaries();
+
+ // THEN we don't add any section headers
+ verify(mNssl, never()).addView(eq(mSectionsManager.getGentleHeaderView()), anyInt());
+ }
+
+ @Test
+ public void testMoveHeaderForward() {
+ // GIVEN a stack that originally had a header between the HI and LO sections
+ setStackState(
+ ChildType.HIPRI,
+ ChildType.HIPRI,
+ ChildType.HIPRI,
+ ChildType.LOPRI);
+ mSectionsManager.updateSectionBoundaries();
+
+ // WHEN the LO section moves forward
+ setStackState(
+ ChildType.HIPRI,
+ ChildType.HIPRI,
+ ChildType.LOPRI,
+ ChildType.HEADER,
+ ChildType.LOPRI);
+ mSectionsManager.updateSectionBoundaries();
+
+ // THEN the LO section header is also moved forward
+ verify(mNssl).changeViewPosition(mSectionsManager.getGentleHeaderView(), 2);
+ }
+
+ @Test
+ public void testMoveHeaderBackward() {
+ // GIVEN a stack that originally had a header between the HI and LO sections
+ setStackState(
+ ChildType.HIPRI,
+ ChildType.LOPRI,
+ ChildType.LOPRI,
+ ChildType.LOPRI);
+ mSectionsManager.updateSectionBoundaries();
+
+ // WHEN the LO section moves backward
+ setStackState(
+ ChildType.HIPRI,
+ ChildType.HEADER,
+ ChildType.HIPRI,
+ ChildType.HIPRI,
+ ChildType.LOPRI);
+ mSectionsManager.updateSectionBoundaries();
+
+ // THEN the LO section header is also moved backward (with appropriate index shifting)
+ verify(mNssl).changeViewPosition(mSectionsManager.getGentleHeaderView(), 3);
+ }
+
+ @Test
+ public void testHeaderRemovedFromTransientParent() {
+ // GIVEN a stack where the header is animating away
+ setStackState(
+ ChildType.HIPRI,
+ ChildType.LOPRI,
+ ChildType.LOPRI,
+ ChildType.LOPRI);
+ mSectionsManager.updateSectionBoundaries();
+ setStackState(
+ ChildType.HIPRI,
+ ChildType.HEADER);
+ mSectionsManager.updateSectionBoundaries();
+ clearInvocations(mNssl);
+
+ ViewGroup transientParent = mock(ViewGroup.class);
+ mSectionsManager.getGentleHeaderView().setTransientContainer(transientParent);
+
+ // WHEN the LO section reappears
+ setStackState(
+ ChildType.HIPRI,
+ ChildType.LOPRI);
+ mSectionsManager.updateSectionBoundaries();
+
+ // THEN the header is first removed from the transient parent before being added to the
+ // NSSL.
+ verify(transientParent).removeTransientView(mSectionsManager.getGentleHeaderView());
+ verify(mNssl).addView(mSectionsManager.getGentleHeaderView(), 1);
+ }
+
+ private enum ChildType { HEADER, HIPRI, LOPRI }
+
+ private void setStackState(ChildType... children) {
+ when(mNssl.getChildCount()).thenReturn(children.length);
+ for (int i = 0; i < children.length; i++) {
+ View child;
+ switch (children[i]) {
+ case HEADER:
+ child = mSectionsManager.getGentleHeaderView();
+ break;
+ case HIPRI:
+ case LOPRI:
+ ExpandableNotificationRow notifRow = mock(ExpandableNotificationRow.class,
+ RETURNS_DEEP_STUBS);
+ when(notifRow.getVisibility()).thenReturn(View.VISIBLE);
+ when(notifRow.getEntry().isHighPriority())
+ .thenReturn(children[i] == ChildType.HIPRI);
+ when(notifRow.getParent()).thenReturn(mNssl);
+ child = notifRow;
+ break;
+ default:
+ throw new RuntimeException("Unknown ChildType: " + children[i]);
+ }
+ when(mNssl.getChildAt(i)).thenReturn(child);
+ when(mNssl.indexOfChild(child)).thenReturn(i);
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 04f911a..09b8062 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -46,6 +46,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.systemui.ActivityStarterDelegate;
import com.android.systemui.Dependency;
import com.android.systemui.ExpandHelper;
import com.android.systemui.InitController;
@@ -118,6 +119,11 @@
@Before
@UiThreadTest
public void setUp() throws Exception {
+ mOriginalInterruptionModelSetting = Settings.Secure.getInt(mContext.getContentResolver(),
+ NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
+
// Inject dependencies before initializing the layout
mDependency.injectTestDependency(
NotificationBlockingHelperManager.class,
@@ -146,7 +152,8 @@
mStackScrollerInternal = new NotificationStackScrollLayout(getContext(), null,
true /* allowLongPress */, mNotificationRoundnessManager,
new AmbientPulseManager(mContext),
- mock(DynamicPrivacyController.class));
+ mock(DynamicPrivacyController.class),
+ mock(ActivityStarterDelegate.class));
mStackScroller = spy(mStackScrollerInternal);
mStackScroller.setShelf(notificationShelf);
mStackScroller.setStatusBar(mBar);
@@ -166,11 +173,6 @@
doNothing().when(mExpandHelper).cancelImmediately();
doNothing().when(notificationShelf).setAnimationsEnabled(anyBoolean());
doNothing().when(notificationShelf).fadeInTranslating();
-
- mOriginalInterruptionModelSetting = Settings.Secure.getInt(mContext.getContentResolver(),
- NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
- Settings.Secure.putInt(mContext.getContentResolver(),
- NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
}
@After
@@ -350,62 +352,6 @@
}
@Test
- public void testUpdateGapIndex_allHighPriority() {
- when(mStackScroller.getChildCount()).thenReturn(3);
- for (int i = 0; i < 3; i++) {
- ExpandableNotificationRow row = mock(ExpandableNotificationRow.class,
- RETURNS_DEEP_STUBS);
- String key = Integer.toString(i);
- when(row.getStatusBarNotification().getKey()).thenReturn(key);
- when(row.getEntry().isHighPriority()).thenReturn(true);
- when(mStackScroller.getChildAt(i)).thenReturn(row);
- }
-
- mStackScroller.updateSectionBoundaries();
- assertEquals(-1, mStackScroller.getSectionBoundaryIndex(0));
- }
-
- @Test
- public void testUpdateGapIndex_allLowPriority() {
- when(mStackScroller.getChildCount()).thenReturn(3);
- for (int i = 0; i < 3; i++) {
- ExpandableNotificationRow row = mock(ExpandableNotificationRow.class,
- RETURNS_DEEP_STUBS);
- String key = Integer.toString(i);
- when(row.getStatusBarNotification().getKey()).thenReturn(key);
- when(row.getEntry().isHighPriority()).thenReturn(false);
- when(mStackScroller.getChildAt(i)).thenReturn(row);
- }
-
- mStackScroller.updateSectionBoundaries();
- assertEquals(-1, mStackScroller.getSectionBoundaryIndex(0));
- }
-
- @Test
- public void testUpdateGapIndex_gapExists() {
- when(mStackScroller.getChildCount()).thenReturn(6);
- for (int i = 0; i < 6; i++) {
- ExpandableNotificationRow row = mock(ExpandableNotificationRow.class,
- RETURNS_DEEP_STUBS);
- String key = Integer.toString(i);
- when(row.getStatusBarNotification().getKey()).thenReturn(key);
- when(row.getEntry().isHighPriority()).thenReturn(i < 3);
- when(mStackScroller.getChildAt(i)).thenReturn(row);
- }
-
- mStackScroller.updateSectionBoundaries();
- assertEquals(3, mStackScroller.getSectionBoundaryIndex(0));
- }
-
- @Test
- public void testUpdateGapIndex_empty() {
- when(mStackScroller.getChildCount()).thenReturn(0);
-
- mStackScroller.updateSectionBoundaries();
- assertEquals(-1, mStackScroller.getSectionBoundaryIndex(0));
- }
-
- @Test
public void testOnDensityOrFontScaleChanged_reInflatesFooterViews() {
clearInvocations(mStackScroller);
mStackScroller.onDensityOrFontScaleChanged();
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 8fe0c70..3bc5f3e 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
@@ -48,9 +48,9 @@
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.plugins.FalsingManager;
import org.junit.Assert;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 51fb47b..06d76eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import static android.service.notification.NotificationListenerService.REASON_CLICK;
+
import static org.mockito.AdditionalAnswers.answerVoid;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -224,7 +226,7 @@
eq(sbn.getKey()), any(NotificationVisibility.class));
// Notification is removed due to FLAG_AUTO_CANCEL
- verify(mEntryManager).performRemoveNotification(eq(sbn));
+ verify(mEntryManager).performRemoveNotification(eq(sbn), eq(REASON_CLICK));
}
@Test
@@ -253,7 +255,7 @@
verifyZeroInteractions(mContentIntent);
// Notification should not be cancelled.
- verify(mEntryManager, never()).performRemoveNotification(eq(sbn));
+ verify(mEntryManager, never()).performRemoveNotification(eq(sbn), anyInt());
}
@Test
@@ -283,7 +285,7 @@
verifyZeroInteractions(mContentIntent);
// Notification should not be cancelled.
- verify(mEntryManager, never()).performRemoveNotification(eq(sbn));
+ verify(mEntryManager, never()).performRemoveNotification(eq(sbn), anyInt());
}
@Test
@@ -315,6 +317,6 @@
verifyNoMoreInteractions(mContentIntent);
// Notification should not be cancelled.
- verify(mEntryManager, never()).performRemoveNotification(eq(sbn));
+ verify(mEntryManager, never()).performRemoveNotification(eq(sbn), anyInt());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
index a88a595..a97832f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
@@ -70,7 +70,8 @@
mNotificationLockscreenUserManager);
mDependency.putComponent(CommandQueue.class, mock(CommandQueue.class));
- mRemoteInputCallback = spy(new StatusBarRemoteInputCallback(mContext));
+ mRemoteInputCallback = spy(new StatusBarRemoteInputCallback(mContext,
+ mock(NotificationGroupManager.class)));
mRemoteInputCallback.mChallengeReceiver = mRemoteInputCallback.new ChallengeReceiver();
}
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 fb16465..79e05c3 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
@@ -78,12 +78,12 @@
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
index 7f3c34e..766ad97 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
@@ -17,7 +17,10 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -198,4 +201,32 @@
assertFalse(mBluetoothControllerImpl.isBluetoothConnecting());
assertFalse(mBluetoothControllerImpl.isBluetoothConnected());
}
+
+ @Test
+ public void testOnACLConnectionStateChange_updatesBluetoothStateOnConnection()
+ throws Exception {
+ BluetoothController.Callback callback = mock(BluetoothController.Callback.class);
+ mBluetoothControllerImpl.addCallback(callback);
+
+ assertFalse(mBluetoothControllerImpl.isBluetoothConnected());
+ CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
+ mDevices.add(device);
+ when(device.isConnected()).thenReturn(true);
+ when(device.getMaxConnectionState()).thenReturn(BluetoothProfile.STATE_CONNECTED);
+ reset(callback);
+ mBluetoothControllerImpl.onAclConnectionStateChanged(device,
+ BluetoothProfile.STATE_CONNECTED);
+
+ // Grab the main looper, we'll need it later.
+ TestableLooper mainLooper = new TestableLooper(Looper.getMainLooper());
+
+ try {
+ mTestableLooper.processAllMessages();
+ mainLooper.processAllMessages();
+ } finally {
+ mainLooper.destroy();
+ }
+ assertTrue(mBluetoothControllerImpl.isBluetoothConnected());
+ verify(callback, atLeastOnce()).onBluetoothStateChange(anyBoolean());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayManagerTest.java
index 4659afc..c99deb6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayManagerTest.java
@@ -22,6 +22,7 @@
import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_ICON_LAUNCHER;
import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_ICON_SETTINGS;
import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_ICON_SYSUI;
+import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_ICON_THEME_PICKER;
import static com.android.systemui.theme.ThemeOverlayManager.OVERLAY_CATEGORY_SHAPE;
import static com.android.systemui.theme.ThemeOverlayManager.SETTINGS_PACKAGE;
import static com.android.systemui.theme.ThemeOverlayManager.SYSTEM_USER_CATEGORIES;
@@ -74,6 +75,7 @@
}
}
+ private static final String THEMEPICKER_PACKAGE = "com.android.wallpaper";
private static final String LAUNCHER_PACKAGE = "com.android.launcher3";
private static final UserHandle TEST_USER = UserHandle.of(5);
private static final Set<UserHandle> TEST_USER_HANDLES = Sets.newHashSet(TEST_USER);
@@ -87,7 +89,7 @@
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
mManager = new ThemeOverlayManager(mOverlayManager, MoreExecutors.directExecutor(),
- LAUNCHER_PACKAGE);
+ LAUNCHER_PACKAGE, THEMEPICKER_PACKAGE);
when(mOverlayManager.getOverlayInfosForTarget(ANDROID_PACKAGE, UserHandle.SYSTEM))
.thenReturn(Lists.newArrayList(
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_COLOR,
@@ -124,6 +126,12 @@
LAUNCHER_PACKAGE, OVERLAY_CATEGORY_ICON_LAUNCHER, false),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_LAUNCHER,
LAUNCHER_PACKAGE, OVERLAY_CATEGORY_ICON_LAUNCHER, true)));
+ when(mOverlayManager.getOverlayInfosForTarget(THEMEPICKER_PACKAGE, UserHandle.SYSTEM))
+ .thenReturn(Lists.newArrayList(
+ createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_ICON_THEME_PICKER,
+ THEMEPICKER_PACKAGE, OVERLAY_CATEGORY_ICON_THEME_PICKER, false),
+ createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_THEME_PICKER,
+ THEMEPICKER_PACKAGE, OVERLAY_CATEGORY_ICON_THEME_PICKER, true)));
}
@Test
@@ -222,6 +230,8 @@
verify(mOverlayManager, never()).getOverlayInfosForTarget(SYSUI_PACKAGE, UserHandle.SYSTEM);
verify(mOverlayManager, never()).getOverlayInfosForTarget(LAUNCHER_PACKAGE,
UserHandle.SYSTEM);
+ verify(mOverlayManager, never()).getOverlayInfosForTarget(THEMEPICKER_PACKAGE,
+ UserHandle.SYSTEM);
}
private static OverlayInfo createOverlayInfo(String packageName, String targetPackageName,
diff --git a/packages/VpnDialogs/res/values-mr/strings.xml b/packages/VpnDialogs/res/values-mr/strings.xml
index 318f854..41d7429 100644
--- a/packages/VpnDialogs/res/values-mr/strings.xml
+++ b/packages/VpnDialogs/res/values-mr/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"कनेक्शन विनंती"</string>
- <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> नेटवर्क रहदारीचे परीक्षण करण्यासाठी त्यास अनुमती देणारे VPN कनेक्शन सेट करू इच्छितो. तुम्हाला स्त्रोत विश्वसनीय वाटत असेल तरच स्वीकार करा. <br /> <br /> <img src=vpn_icon /> VPN सक्रिय असताना आपल्या स्क्रीनच्या शीर्षावर दिसते."</string>
+ <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> नेटवर्क रहदारीचे परीक्षण करण्यासाठी त्यास अनुमती देणारे VPN कनेक्शन सेट करू इच्छितो. तुम्हाला स्रोत विश्वसनीय वाटत असेल तरच स्वीकार करा. <br /> <br /> <img src=vpn_icon /> VPN सक्रिय असताना आपल्या स्क्रीनच्या शीर्षावर दिसते."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN कनेक्ट केले"</string>
<string name="session" msgid="6470628549473641030">"सत्र:"</string>
<string name="duration" msgid="3584782459928719435">"कालावधी:"</string>
diff --git a/packages/VpnDialogs/res/values-zh-rHK/strings.xml b/packages/VpnDialogs/res/values-zh-rHK/strings.xml
index f70cd51..49605b0 100644
--- a/packages/VpnDialogs/res/values-zh-rHK/strings.xml
+++ b/packages/VpnDialogs/res/values-zh-rHK/strings.xml
@@ -24,7 +24,7 @@
<string name="data_transmitted" msgid="7988167672982199061">"已傳送:"</string>
<string name="data_received" msgid="4062776929376067820">"已接收:"</string>
<string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> 位元組 / <xliff:g id="NUMBER_1">%2$s</xliff:g> 封包"</string>
- <string name="always_on_disconnected_title" msgid="1906740176262776166">"無法連線至永遠開啟的 VPN"</string>
+ <string name="always_on_disconnected_title" msgid="1906740176262776166">"無法連線至保持開啟的 VPN"</string>
<string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> 已設定為隨時保持連線,但目前無法連線。在重新連線至 <xliff:g id="VPN_APP_1">%1$s</xliff:g> 前,您的手機將會使用公共網絡。"</string>
<string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> 已設定為隨時保持連線,但目前無法連線。在重新連線至 VPN 前,您將無法連線至網絡。"</string>
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index b9b3a61..2675e90 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -32,14 +32,17 @@
IconPackCircularLauncherOverlay \
IconPackCircularSettingsOverlay \
IconPackCircularSystemUIOverlay \
+ IconPackCircularThemePickerOverlay \
IconPackFilledAndroidOverlay \
IconPackFilledLauncherOverlay \
IconPackFilledSettingsOverlay \
IconPackFilledSystemUIOverlay \
+ IconPackFilledThemePickerOverlay \
IconPackRoundedAndroidOverlay \
IconPackRoundedLauncherOverlay \
IconPackRoundedSettingsOverlay \
IconPackRoundedSystemUIOverlay \
+ IconPackRoundedThemePickerUIOverlay \
IconShapeRoundedRectOverlay \
IconShapeSquareOverlay \
IconShapeSquircleOverlay \
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_0.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_0.xml
new file mode 100644
index 0000000..1be546840e
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_0.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="fillAlpha" android:duration="150"
+ android:startOffset="0" android:valueFrom="0.3"
+ android:valueTo="0.3" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="150" android:valueFrom="0.3"
+ android:valueTo="1" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="483"
+ android:startOffset="167" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="650" android:valueFrom="1"
+ android:valueTo="0.3" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+</set>
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_1.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_1.xml
new file mode 100644
index 0000000..c9fd424
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_1.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="fillAlpha" android:duration="317"
+ android:startOffset="0" android:valueFrom="0.3"
+ android:valueTo="0.3" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="317" android:valueFrom="0.3"
+ android:valueTo="1" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="483"
+ android:startOffset="333" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="817" android:valueFrom="1"
+ android:valueTo="0.3" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+</set>
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_2.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_2.xml
new file mode 100644
index 0000000..b34d308
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_2.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="fillAlpha" android:duration="483"
+ android:startOffset="0" android:valueFrom="0.3"
+ android:valueTo="0.3" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="483" android:valueFrom="0.3"
+ android:valueTo="1" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="483"
+ android:startOffset="500" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="983" android:valueFrom="1"
+ android:valueTo="0.3" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+</set>
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_3.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_3.xml
new file mode 100644
index 0000000..9d2b3a4f
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_3.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="fillAlpha" android:duration="650"
+ android:startOffset="0" android:valueFrom="0.3"
+ android:valueTo="0.3" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="650" android:valueFrom="0.3"
+ android:valueTo="1" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="483"
+ android:startOffset="667" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+ <objectAnimator android:propertyName="fillAlpha" android:duration="17"
+ android:startOffset="1150" android:valueFrom="1"
+ android:valueTo="0.3" android:valueType="floatType"
+ android:interpolator="@*android:interpolator/transient_interpolator" />
+</set>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_4.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/global_action_panel_scrim.xml
copy to packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_4.xml
index 8b8258f..943893d 100644
--- a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/anim/ic_signal_wifi_transient_animation_4.xml
@@ -14,13 +14,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:centerY="0.45"
- android:startColor="#dc3c4043"
- android:centerColor="#dc3c4043"
- android:endColor="#4d3c4043"
- android:angle="270" />
-</shape>
\ No newline at end of file
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="1250"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+</set>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml
new file mode 100644
index 0000000..bd5aefa
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@*android:drawable/ic_bluetooth_transient_animation_drawable" >
+ <target
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:animation="@*android:anim/ic_bluetooth_transient_animation_0" />
+ <target
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:animation="@*android:anim/ic_bluetooth_transient_animation_1" />
+ <target
+ android:name="time_group"
+ android:animation="@*android:anim/ic_bluetooth_transient_animation_2" />
+</animated-vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bluetooth_transient_animation_drawable.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bluetooth_transient_animation_drawable.xml
new file mode 100644
index 0000000..b7acaeb
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bluetooth_transient_animation_drawable.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:translateX="3.75"
+ android:translateY="1.75" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M1.22 3.22 C0.93,3.51 0.93,3.99 1.22,4.28 C1.22,4.28 7.19,10.25 7.19,10.25 C7.19,10.25 1.22,16.22 1.22,16.22 C0.93,16.51 0.93,16.99 1.22,17.28 C1.37,17.43 1.56,17.5 1.75,17.5 C1.94,17.5 2.13,17.43 2.28,17.28 C2.28,17.28 7.25,12.31 7.25,12.31 C7.25,12.31 7.25,20.25 7.25,20.25 C7.25,20.25 8,20.25 8,20.25 C10.96,20.25 13.37,17.84 13.37,14.88 C13.37,12.91 12.31,11.19 10.73,10.25 C12.31,9.31 13.37,7.59 13.37,5.63 C13.37,2.66 10.96,0.25 8,0.25 C8,0.25 7.25,0.25 7.25,0.25 C7.25,0.25 7.25,8.19 7.25,8.19 C7.25,8.19 2.28,3.22 2.28,3.22 C1.99,2.93 1.51,2.93 1.22,3.22c M8.75 1.82 C10.52,2.17 11.87,3.75 11.87,5.63 C11.87,7.5 10.52,9.08 8.75,9.43 C8.75,9.43 8.75,1.82 8.75,1.82c M8.75 11.07 C10.52,11.42 11.87,13 11.87,14.88 C11.87,16.75 10.52,18.33 8.75,18.68 C8.75,18.68 8.75,11.07 8.75,11.07c " />
+ </group>
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="3.75"
+ android:translateY="1.75" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M15.25 9.25 C14.7,9.25 14.25,9.7 14.25,10.25 C14.25,10.8 14.7,11.25 15.25,11.25 C15.8,11.25 16.25,10.8 16.25,10.25 C16.25,9.7 15.8,9.25 15.25,9.25c " />
+ </group>
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="3.75"
+ android:translateY="1.75" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M0.25 10.25 C0.25,10.8 0.7,11.25 1.25,11.25 C1.8,11.25 2.25,10.8 2.25,10.25 C2.25,9.7 1.8,9.25 1.25,9.25 C0.7,9.25 0.25,9.7 0.25,10.25c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+</vector>
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_headset_hfp.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_headset_hfp.xml
index 5501dd0..aec7bf4 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_headset_hfp.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_headset_hfp.xml
@@ -20,7 +20,6 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path android:pathData="M0,0h24v24H0V0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M12,1c-4.96,0-9,4.04-9,9v6.78C3,18.56,4.41,20,6.13,20H9v-8H4.5v-2c0-4.13,3.36-7.5,7.5-7.5s7.5,3.36,7.5,7.5v2H15v8h2.87 c0.59,0,1.13-0.18,1.6-0.47c-0.14,1.11-1.08,1.97-2.22,1.97h-4.5c-0.41,0-0.75,0.34-0.75,0.75S12.34,23,12.75,23h4.5 c2.07,0,3.75-1.68,3.75-3.75V10C21,5.04,16.96,1,12,1z M7.5,18.5H6.13c-0.9,0-1.63-0.77-1.63-1.72V13.5h3V18.5z M17.87,18.5H16.5 v-5h3V16v0.78C19.5,17.73,18.77,18.5,17.87,18.5z" />
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_hearing_aid.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_hearing_aid.xml
index d791ce1..6397e07 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_hearing_aid.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_hearing_aid.xml
@@ -19,7 +19,6 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path android:pathData="M0,0h24v24H0V0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M6.73,1.73C6.42,1.46,5.94,1.5,5.67,1.81C3.95,3.8,3,6.35,3,9s0.95,5.2,2.67,7.19c0.15,0.17,0.36,0.26,0.57,0.26 c0.17,0,0.35-0.06,0.49-0.18c0.31-0.27,0.35-0.75,0.08-1.06C5.32,13.49,4.5,11.29,4.5,9s0.82-4.49,2.31-6.21 C7.08,2.48,7.04,2,6.73,1.73z M20.34,18.02c-0.4-0.09-0.81,0.15-0.9,0.56c-0.27,1.13-1.27,1.92-2.43,1.92 c-0.35,0-0.71-0.08-0.98-0.2c-0.96-0.51-1.48-1.21-1.96-2.67c-0.47-1.43-1.36-2.11-2.22-2.77c-0.79-0.61-1.68-1.29-2.45-2.68 C8.81,11.14,8.5,10.02,8.5,9c0-3.08,2.42-5.5,5.5-5.5c2.84,0,5.14,2.03,5.46,4.83c0.05,0.41,0.43,0.71,0.83,0.66 C20.7,8.95,21,8.58,20.95,8.17C20.54,4.59,17.62,2,14,2c-3.92,0-7,3.08-7,7c0,1.27,0.38,2.65,1.07,3.9 c0.92,1.66,2.03,2.52,2.85,3.15c0.8,0.62,1.38,1.06,1.71,2.05c0.61,1.85,1.36,2.84,2.73,3.55C15.87,21.88,16.43,22,17,22 c1.86,0,3.46-1.27,3.89-3.08C20.99,18.52,20.74,18.12,20.34,18.02z M11.5,9c0,1.38,1.12,2.5,2.5,2.5s2.5-1.12,2.5-2.5 S15.38,6.5,14,6.5S11.5,7.62,11.5,9z M15,9c0,0.55-0.45,1-1,1s-1-0.45-1-1s0.45-1,1-1S15,8.45,15,9z" />
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_network_pan.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_network_pan.xml
index 54c525b..c7a0266 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_network_pan.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_network_pan.xml
@@ -22,10 +22,10 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M18.75,17.75c0.2,0,0.4-0.08,0.55-0.24c1.42-1.53,2.2-3.49,2.2-5.51c0-2.02-0.78-3.97-2.2-5.51 c-0.28-0.3-0.76-0.32-1.06-0.04c-0.3,0.28-0.32,0.76-0.04,1.06C19.36,8.77,20,10.36,20,12c0,1.64-0.64,3.24-1.8,4.49 c-0.28,0.3-0.26,0.78,0.04,1.06C18.38,17.68,18.57,17.75,18.75,17.75z" />
+ android:pathData="M18.2,16.49c-0.28,0.3-0.26,0.78,0.04,1.06c0.14,0.13,0.33,0.2,0.51,0.2c0.2,0,0.4-0.08,0.55-0.24 c1.42-1.53,2.2-3.49,2.2-5.51c0-2.02-0.78-3.97-2.2-5.51c-0.28-0.3-0.76-0.32-1.06-0.04c-0.3,0.28-0.32,0.76-0.04,1.06 C19.36,8.77,20,10.36,20,12C20,13.64,19.36,15.23,18.2,16.49z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M16.34,14.64c0.15,0.15,0.34,0.22,0.53,0.22c0.19,0,0.38-0.07,0.53-0.22c0.71-0.7,1.1-1.64,1.1-2.64 c0-1-0.39-1.94-1.09-2.64c-0.29-0.29-0.77-0.29-1.06,0c-0.29,0.29-0.29,0.77,0,1.06C16.77,10.85,17,11.41,17,12 c0,0.6-0.23,1.16-0.66,1.58C16.05,13.87,16.05,14.35,16.34,14.64z" />
+ android:pathData="M16.35,9.36c-0.29,0.29-0.29,0.77,0,1.06C16.77,10.85,17,11.41,17,12s-0.23,1.16-0.66,1.58c-0.29,0.29-0.3,0.77,0,1.06 c0.15,0.15,0.34,0.22,0.53,0.22c0.19,0,0.38-0.07,0.53-0.22c0.71-0.7,1.1-1.64,1.1-2.64c0-1-0.39-1.94-1.09-2.64 C17.12,9.07,16.64,9.07,16.35,9.36z" />
<path
android:fillColor="@android:color/white"
android:pathData="M2.97,19.03c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22L9,14.06V22h0.75c2.96,0,5.37-2.41,5.37-5.38 c0-1.97-1.06-3.69-2.64-4.62c1.58-0.94,2.64-2.66,2.64-4.62C15.12,4.41,12.71,2,9.75,2H9v7.94L4.03,4.97 c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06L8.94,12l-5.97,5.97C2.68,18.26,2.68,18.74,2.97,19.03z M10.5,3.57 c1.78,0.35,3.12,1.92,3.12,3.8s-1.34,3.45-3.12,3.8V3.57z M10.5,12.82c1.78,0.35,3.12,1.92,3.12,3.8s-1.34,3.45-3.12,3.8V12.82z" />
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_pointing_hid.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_pointing_hid.xml
index b822125..a5f6606 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_pointing_hid.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_pointing_hid.xml
@@ -20,7 +20,6 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path android:pathData="M0,0h24v24H0V0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M12,1.07c-3.87,0-7,3.13-7,7V16c0,3.87,3.13,7,7,7s7-3.13,7-7V8.07C19,4.2,15.87,1.07,12,1.07z M17.5,16 c0,3.03-2.47,5.5-5.5,5.5S6.5,19.03,6.5,16v-5h11V16z M17.5,9.5h-11V8.07c0-3.03,2.47-5.5,5.5-5.5s5.5,2.47,5.5,5.5V9.5z M12,4.04 c-0.41,0-0.75,0.34-0.75,0.75v2.46C11.25,7.66,11.59,8,12,8s0.75-0.34,0.75-0.75V4.79C12.75,4.37,12.41,4.04,12,4.04z" />
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_corp_badge.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_corp_badge.xml
new file mode 100644
index 0000000..586e7a6
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_corp_badge.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="@*android:color/accent_device_default_light"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M16,4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H2v12c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V6h-6V4z M9.5,4 c0-0.3,0.2-0.5,0.5-0.5h4c0.3,0,0.5,0.2,0.5,0.5v2h-5V4z M20.5,7.5V18c0,0.8-0.7,1.5-1.5,1.5H5c-0.8,0-1.5-0.7-1.5-1.5V7.5H20.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 12.3 C 12.6627416998 12.3 13.2 12.8372583002 13.2 13.5 C 13.2 14.1627416998 12.6627416998 14.7 12 14.7 C 11.3372583002 14.7 10.8 14.1627416998 10.8 13.5 C 10.8 12.8372583002 11.3372583002 12.3 12 12.3 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_expand_more.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_expand_more.xml
index a1a71e3..6419515 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_expand_more.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_expand_more.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_file_copy.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_file_copy.xml
index 2d525dc..dc6ab95 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_file_copy.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_file_copy.xml
@@ -23,5 +23,4 @@
<path
android:fillColor="@android:color/white"
android:pathData="M17.5,21.5H4c-0.3,0-0.5-0.2-0.5-0.5V7.5C3.5,7.2,3.3,7,3,7H2.5C2.2,7,2,7.2,2,7.5v14C2,22.3,2.7,23,3.5,23h14 c0.3,0,0.5-0.2,0.5-0.5V22C18,21.7,17.8,21.5,17.5,21.5z M21,16V4c0-1.7-1.4-3-3-3H9C7.3,1,6,2.3,6,4v12c0,1.6,1.3,3,3,3h9 C19.6,19,21,17.6,21,16z M18,17.5H9c-0.8,0-1.5-0.7-1.5-1.5V4c0-0.8,0.7-1.5,1.5-1.5h9c0.8,0,1.5,0.7,1.5,1.5v12 C19.5,16.8,18.8,17.5,18,17.5z" />
- <path android:pathData="M0,0h24v24H0V0z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml
new file mode 100644
index 0000000..9d43e51
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@*android:drawable/ic_hotspot_transient_animation_drawable" >
+ <target
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_0" />
+ <target
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_1" />
+ <target
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_2" />
+ <target
+ android:name="time_group"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_3" />
+</animated-vector>
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_hotspot_transient_animation_drawable.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_hotspot_transient_animation_drawable.xml
new file mode 100644
index 0000000..15f2735
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_hotspot_transient_animation_drawable.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="2"
+ android:translateY="1.552999999999999" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M10 12.45 C9.17,12.45 8.5,11.77 8.5,10.95 C8.5,10.12 9.17,9.45 10,9.45 C10.83,9.45 11.5,10.12 11.5,10.95 C11.5,11.77 10.83,12.45 10,12.45c " />
+ <path
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M6.47 15.23 C6.27,15.23 6.08,15.16 5.94,15.01 C4.85,13.93 4.25,12.48 4.25,10.95 C4.25,9.41 4.85,7.97 5.94,6.88 C8.18,4.64 11.82,4.64 14.07,6.88 C15.15,7.97 15.75,9.41 15.75,10.95 C15.75,12.48 15.15,13.93 14.07,15.01 C13.77,15.3 13.3,15.3 13.01,15.01 C12.71,14.72 12.71,14.24 13.01,13.95 C13.81,13.15 14.25,12.08 14.25,10.95 C14.25,9.81 13.81,8.74 13.01,7.94 C11.35,6.28 8.65,6.28 6.99,7.94 C6.19,8.75 5.75,9.81 5.75,10.95 C5.75,12.08 6.19,13.15 6.99,13.95 C7.29,14.25 7.29,14.72 6.99,15.01 C6.85,15.16 6.66,15.23 6.47,15.23c " />
+ <path
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M16.36 18.06 C16.17,18.06 15.98,17.99 15.83,17.84 C15.54,17.55 15.54,17.07 15.83,16.78 C17.39,15.22 18.25,13.15 18.25,10.95 C18.25,8.74 17.39,6.67 15.83,5.11 C12.62,1.9 7.38,1.9 4.17,5.11 C2.61,6.67 1.75,8.74 1.75,10.95 C1.75,13.15 2.61,15.22 4.17,16.78 C4.46,17.07 4.46,17.55 4.17,17.84 C3.87,18.13 3.4,18.13 3.11,17.84 C1.26,16 0.25,13.55 0.25,10.95 C0.25,8.34 1.26,5.89 3.11,4.05 C6.91,0.25 13.09,0.25 16.89,4.05 C18.74,5.89 19.75,8.34 19.75,10.95 C19.75,13.55 18.74,16 16.89,17.84 C16.75,17.99 16.56,18.06 16.36,18.06c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+</vector>
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_battery_saver.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
new file mode 100644
index 0000000..a558337
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9.75,13.75h1.5v1.5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-1.5h1.5c0.41,0,0.75-0.34,0.75-0.75 s-0.34-0.75-0.75-0.75h-1.5v-1.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v1.5h-1.5C9.34,12.25,9,12.59,9,13 S9.34,13.75,9.75,13.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,19c0,1.66,1.34,3,3,3h6c1.66,0,3-1.34,3-3V7c0-1.66-1.34-3-3-3h-1c0-0.55-0.45-1-1-1h-2c-0.55,0-1,0.45-1,1H9 C7.34,4,6,5.34,6,7V19z M7.5,7c0-0.83,0.67-1.5,1.5-1.5h6c0.83,0,1.5,0.67,1.5,1.5v12c0,0.83-0.67,1.5-1.5,1.5H9 c-0.83,0-1.5-0.67-1.5-1.5V7z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml
new file mode 100644
index 0000000..e09aeb7
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_0_5_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_0_5_bar.xml
new file mode 100644
index 0000000..ed510f0
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_0_5_bar.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M20,22h-1.5V4.75C18.5,4.34,18.84,4,19.25,4l0,0C19.66,4,20,4.34,20,4.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M16.5,22H15V8.75C15,8.34,15.34,8,15.75,8h0c0.41,0,0.75,0.34,0.75,0.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M13,22h-1.5v-9.25c0-0.41,0.34-0.75,0.75-0.75h0c0.41,0,0.75,0.34,0.75,0.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M9.5,22H8v-6.25C8,15.34,8.34,15,8.75,15h0c0.41,0,0.75,0.34,0.75,0.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M6,22H4.5v-2.25C4.5,19.34,4.84,19,5.25,19h0C5.66,19,6,19.34,6,19.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml
new file mode 100644
index 0000000..26e96ab
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_1_5_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_1_5_bar.xml
new file mode 100644
index 0000000..7a5e570
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_1_5_bar.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M20,22h-1.5V4.75C18.5,4.34,18.84,4,19.25,4l0,0C19.66,4,20,4.34,20,4.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M16.5,22H15V8.75C15,8.34,15.34,8,15.75,8h0c0.41,0,0.75,0.34,0.75,0.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M13,22h-1.5v-9.25c0-0.41,0.34-0.75,0.75-0.75h0c0.41,0,0.75,0.34,0.75,0.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M9.5,22H8v-6.25C8,15.34,8.34,15,8.75,15h0c0.41,0,0.75,0.34,0.75,0.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,22H4.5v-2.25C4.5,19.34,4.84,19,5.25,19h0C5.66,19,6,19.34,6,19.75V22z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml
new file mode 100644
index 0000000..53be899
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_2_5_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_2_5_bar.xml
new file mode 100644
index 0000000..06be365
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_2_5_bar.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M20,22h-1.5V4.75C18.5,4.34,18.84,4,19.25,4l0,0C19.66,4,20,4.34,20,4.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M16.5,22H15V8.75C15,8.34,15.34,8,15.75,8h0c0.41,0,0.75,0.34,0.75,0.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M13,22h-1.5v-9.25c0-0.41,0.34-0.75,0.75-0.75h0c0.41,0,0.75,0.34,0.75,0.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9.5,22H8v-6.25C8,15.34,8.34,15,8.75,15h0c0.41,0,0.75,0.34,0.75,0.75V22z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,22H4.5v-2.25C4.5,19.34,4.84,19,5.25,19h0C5.66,19,6,19.34,6,19.75V22z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml
new file mode 100644
index 0000000..9139bb4
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_3_5_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_3_5_bar.xml
new file mode 100644
index 0000000..f5b82ea
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_3_5_bar.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M20,22h-1.5V4.75C18.5,4.34,18.84,4,19.25,4l0,0C19.66,4,20,4.34,20,4.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M16.5,22H15V8.75C15,8.34,15.34,8,15.75,8h0c0.41,0,0.75,0.34,0.75,0.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M13,22h-1.5v-9.25c0-0.41,0.34-0.75,0.75-0.75h0c0.41,0,0.75,0.34,0.75,0.75V22z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9.5,22H8v-6.25C8,15.34,8.34,15,8.75,15h0c0.41,0,0.75,0.34,0.75,0.75V22z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,22H4.5v-2.25C4.5,19.34,4.84,19,5.25,19h0C5.66,19,6,19.34,6,19.75V22z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml
new file mode 100644
index 0000000..2c8d7012
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_4_5_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_4_5_bar.xml
new file mode 100644
index 0000000..ab2f3f7
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_4_5_bar.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M20,22h-1.5V4.75C18.5,4.34,18.84,4,19.25,4l0,0C19.66,4,20,4.34,20,4.75V22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M16.5,22H15V8.75C15,8.34,15.34,8,15.75,8h0c0.41,0,0.75,0.34,0.75,0.75V22z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M13,22h-1.5v-9.25c0-0.41,0.34-0.75,0.75-0.75h0c0.41,0,0.75,0.34,0.75,0.75V22z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9.5,22H8v-6.25C8,15.34,8.34,15,8.75,15h0c0.41,0,0.75,0.34,0.75,0.75V22z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,22H4.5v-2.25C4.5,19.34,4.84,19,5.25,19h0C5.66,19,6,19.34,6,19.75V22z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_5_5_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_5_5_bar.xml
new file mode 100644
index 0000000..a53768b
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_5_5_bar.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,4.75C20,4.34,19.66,4,19.25,4S18.5,4.34,18.5,4.75V22H20V4.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M15.75,8C15.34,8,15,8.34,15,8.75V22h1.5V8.75C16.5,8.34,16.16,8,15.75,8z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12.25,12c-0.41,0-0.75,0.34-0.75,0.75V22H13v-9.25C13,12.34,12.66,12,12.25,12z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8.75,15C8.34,15,8,15.34,8,15.75V22h1.5v-6.25C9.5,15.34,9.16,15,8.75,15z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M5.25,19c-0.41,0-0.75,0.34-0.75,0.75V22H6v-2.25C6,19.34,5.66,19,5.25,19z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml
new file mode 100644
index 0000000..20418a3
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@*android:drawable/ic_signal_wifi_transient_animation_drawable" >
+ <target
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_0" />
+ <target
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_1" />
+ <target
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_2" />
+ <target
+ android:name="_R_G_L_0_G_D_3_P_0"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_3" />
+ <target
+ android:name="time_group"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_4" />
+</animated-vector>
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation_drawable.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation_drawable.xml
new file mode 100644
index 0000000..6dfe9d7
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation_drawable.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="0.6440000000000001"
+ android:translateY="2.755000000000001" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:fillAlpha="0.3"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M12.86 15.75 C12.86,16.58 12.19,17.25 11.36,17.25 C10.53,17.25 9.86,16.58 9.86,15.75 C9.86,14.92 10.53,14.25 11.36,14.25 C12.19,14.25 12.86,14.92 12.86,15.75c " />
+ <path
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:fillAlpha="0.3"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M15.61 12.25 C15.42,12.25 15.23,12.17 15.08,12.03 C14.09,11.04 12.76,10.5 11.36,10.5 C9.95,10.5 8.63,11.04 7.63,12.03 C7.34,12.32 6.86,12.32 6.57,12.02 C6.28,11.73 6.28,11.26 6.58,10.96 C7.86,9.7 9.55,9 11.36,9 C13.16,9 14.86,9.7 16.14,10.96 C16.43,11.25 16.43,11.73 16.14,12.02 C16,12.17 15.8,12.25 15.61,12.25c " />
+ <path
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:fillAlpha="0.3"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M18.77 9.08 C18.58,9.08 18.39,9.01 18.24,8.86 C16.4,7.02 13.96,6 11.36,6 C8.75,6 6.31,7.02 4.47,8.86 C4.18,9.16 3.7,9.16 3.41,8.86 C3.12,8.57 3.11,8.1 3.41,7.8 C5.53,5.67 8.35,4.5 11.36,4.5 C14.36,4.5 17.18,5.67 19.31,7.8 C19.6,8.1 19.6,8.57 19.3,8.86 C19.16,9.01 18.97,9.08 18.77,9.08c " />
+ <path
+ android:name="_R_G_L_0_G_D_3_P_0"
+ android:fillAlpha="0.3"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M21.96 5.89 C21.77,5.89 21.58,5.82 21.43,5.67 C18.74,2.98 15.16,1.5 11.36,1.5 C7.55,1.5 3.97,2.98 1.28,5.67 C0.99,5.97 0.51,5.97 0.22,5.67 C-0.07,5.38 -0.07,4.91 0.22,4.61 C3.19,1.64 7.15,0 11.36,0 C15.56,0 19.52,1.64 22.49,4.61 C22.78,4.91 22.78,5.38 22.49,5.67 C22.35,5.82 22.15,5.89 21.96,5.89c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+</vector>
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_calendar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_calendar.xml
new file mode 100644
index 0000000..781c0f8
--- /dev/null
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_calendar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 15 12.5 C 16.3807118746 12.5 17.5 13.6192881254 17.5 15 C 17.5 16.3807118746 16.3807118746 17.5 15 17.5 C 13.6192881254 17.5 12.5 16.3807118746 12.5 15 C 12.5 13.6192881254 13.6192881254 12.5 15 12.5 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M17.5,1.75a0.75 0.75 ,0,0,0-1.5,0V3H8V1.75a0.75 0.75 ,0,0,0-1.5,0V3H3V18a3,3,0,0,0,3,3H18a3,3,0,0,0,3-3V3H17.5ZM19.5,18A1.5,1.5,0,0,1,18,19.5H6A1.5,1.5,0,0,1,4.5,18V9h15Zm0-13.5v3H4.5v-3Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_corp.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_corp.xml
index 798907c..b000146 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_corp.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_corp.xml
@@ -1,25 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorHint"
+ android:tint="?android:attr/textColorHint"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M16,4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H2v12c0,1.66,1.34,3,3,3h14c1.66,0,3-1.34,3-3V6h-6V4z M9.5,4 c0-0.28,0.22-0.5,0.5-0.5h4c0.28,0,0.5,0.22,0.5,0.5v2h-5V4z M20.5,7.5V18c0,0.83-0.67,1.5-1.5,1.5H5c-0.83,0-1.5-0.67-1.5-1.5V7.5 H20.5z" />
+ android:pathData="M16,4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H2v12c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V6h-6V4z M9.5,4 c0-0.3,0.2-0.5,0.5-0.5h4c0.3,0,0.5,0.2,0.5,0.5v2h-5V4z M20.5,7.5V18c0,0.8-0.7,1.5-1.5,1.5H5c-0.8,0-1.5-0.7-1.5-1.5V7.5H20.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 12.3 C 12.6627416998 12.3 13.2 12.8372583002 13.2 13.5 C 13.2 14.1627416998 12.6627416998 14.7 12 14.7 C 11.3372583002 14.7 10.8 14.1627416998 10.8 13.5 C 10.8 12.8372583002 11.3372583002 12.3 12 12.3 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_drag_handle.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_drag_handle.xml
index a7ab99e..5e640ba 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_drag_handle.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_drag_handle.xml
@@ -1,24 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!--
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/textColorHint"
+ android:viewportHeight="24"
android:viewportWidth="24"
- android:viewportHeight="24" android:tint="?android:attr/textColorHint">
-
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M4.75,10.5h14.5c0.41,0,0.75-0.34,0.75-0.75S19.66,9,19.25,9H4.75C4.34,9,4,9.34,4,9.75S4.34,10.5,4.75,10.5z" />
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_hourglass_top.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_hourglass_top.xml
index 8160e68..14c6603 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_hourglass_top.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_hourglass_top.xml
@@ -1,28 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!--
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary">
-
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M7,6.8c0,2.23,1.22,4.16,3.02,5.2C8.22,13.04,7,14.97,7,17.2V22h10v-4.8c0-2.23-1.22-4.16-3.02-5.2
-C15.78,10.96,17,9.03,17,6.8V2H7V6.8z
-M15.5,17.2v3.3h-7v-3.3c0-1.6,0.87-3.1,2.26-3.9L12,12.59l1.24,0.71
-C14.63,14.1,15.5,15.6,15.5,17.2z" />
+ android:pathData="M7,6.8c0,2.23,1.22,4.16,3.02,5.2C8.22,13.04,7,14.97,7,17.2V22h10v-4.8c0-2.23-1.22-4.16-3.02-5.2 C15.78,10.96,17,9.03,17,6.8V2H7V6.8z M15.5,17.2v3.3h-7v-3.3c0-1.6,0.87-3.1,2.26-3.9L12,12.59l1.24,0.71 C14.63,14.1,15.5,15.6,15.5,17.2z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_info_no_shadow.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_info_no_shadow.xml
index 82924bb..730f1ea 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_info_no_shadow.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_info_no_shadow.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_install_no_shadow.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_install_no_shadow.xml
new file mode 100644
index 0000000..41b6338
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_install_no_shadow.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,4c-0.41,0-0.75,0.34-0.75,0.75v8.44L8.03,9.97c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06L12,16.06l5.03-5.03 c0.29-0.29,0.29-0.77,0-1.06s-0.77-0.29-1.06,0l-3.22,3.22V4.75C12.75,4.34,12.41,4,12,4z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M4.75,14.5C4.34,14.5,4,14.84,4,15.25v2C4,18.77,5.23,20,6.75,20h10.5c1.52,0,2.75-1.23,2.75-2.75v-2 c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v2c0,0.69-0.56,1.25-1.25,1.25H6.75c-0.69,0-1.25-0.56-1.25-1.25v-2 C5.5,14.84,5.16,14.5,4.75,14.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_palette.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_palette.xml
index 964955b..e086ebd 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_palette.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_palette.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<group
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_pin.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_pin.xml
index 35c0b81..86b4318 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_pin.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_pin.xml
@@ -1,29 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!--
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary">
-
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M4.63,14.62C4.24,15.21,4.66,16,5.37,16h5.88c0,0,0,0,0,0v6.25c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75V16
-c0,0,0,0,0,0h5.84c0.71,0,1.13-0.79,0.74-1.38c-0.84-1.25-1.99-2.26-3.33-2.95V4.5h1.23c0.41,0,0.75-0.34,0.75-0.75
-S17.65,3,17.23,3H6.73C6.32,3,5.98,3.34,5.98,3.75S6.32,4.5,6.73,4.5H8v7.15C6.64,12.34,5.48,13.36,4.63,14.62z
-M14.5,4.5v8.08
-L15.32,13c0.75,0.39,1.43,0.89,2,1.5H6.64c0.58-0.61,1.27-1.12,2.03-1.51l0.82-0.42V4.5H14.5z" />
+ android:pathData="M4.63,14.62C4.24,15.21,4.66,16,5.37,16h5.88c0,0,0,0,0,0v6.25c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75V16 c0,0,0,0,0,0h5.84c0.71,0,1.13-0.79,0.74-1.38c-0.84-1.25-1.99-2.26-3.33-2.95V4.5h1.23c0.41,0,0.75-0.34,0.75-0.75 S17.65,3,17.23,3H6.73C6.32,3,5.98,3.34,5.98,3.75S6.32,4.5,6.73,4.5H8v7.15C6.64,12.34,5.48,13.36,4.63,14.62z M14.5,4.5v8.08 L15.32,13c0.75,0.39,1.43,0.89,2,1.5H6.64c0.58-0.61,1.27-1.12,2.03-1.51l0.82-0.42V4.5H14.5z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_remove_no_shadow.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
index 5fa740d..f739891 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml
index afa0a15..4c9b5d7 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml
@@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_smartspace_preferences.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
index b7d31a2..0717cf9 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_split_screen.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_split_screen.xml
index 649e555..af5cb05 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_split_screen.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_split_screen.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_uninstall_no_shadow.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_uninstall_no_shadow.xml
new file mode 100644
index 0000000..955f5aa
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_uninstall_no_shadow.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9,20h6c1.66,0,3-1.34,3-3V6h0.5c0.41,0,0.75-0.34,0.75-0.75S18.91,4.5,18.5,4.5H18h-3l-1-1h-4l-1,1H6H5.5 c-0.41,0-0.75,0.34-0.75,0.75S5.09,6,5.5,6H6v11C6,18.66,7.34,20,9,20z M16.5,6v11c0,0.83-0.67,1.5-1.5,1.5H9 c-0.83,0-1.5-0.67-1.5-1.5V6H16.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M13.97,16c0.41,0,0.75-0.34,0.75-0.75v-6.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v6.5 C13.22,15.66,13.55,16,13.97,16z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10,16c0.41,0,0.75-0.34,0.75-0.75v-6.5C10.75,8.34,10.41,8,10,8S9.25,8.34,9.25,8.75v6.5C9.25,15.66,9.59,16,10,16z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_warning.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_warning.xml
index e78ae9a..035d9d4 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_warning.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_warning.xml
@@ -1,30 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M4.47,21h15.06c1.54,0,2.5-1.67,1.73-3L13.73,4.99c-0.39-0.67-1.06-1-1.73-1s-1.35,0.33-1.73,1L2.74,18 C1.97,19.33,2.93,21,4.47,21z M4.04,18.75l7.53-13.01c0.13-0.22,0.33-0.25,0.43-0.25s0.31,0.03,0.43,0.25l7.53,13.01 c0.13,0.22,0.05,0.41,0,0.5c-0.05,0.09-0.18,0.25-0.43,0.25H4.47c-0.25,0-0.38-0.16-0.43-0.25C3.98,19.16,3.91,18.97,4.04,18.75z" />
+ android:pathData="M21.26,18L13.73,4.99c-0.39-0.67-1.06-1-1.73-1s-1.35,0.33-1.73,1L2.74,18c-0.77,1.33,0.19,3,1.73,3h15.06 C21.07,21,22.03,19.33,21.26,18z M4.04,19.25c-0.05-0.09-0.13-0.28,0-0.5l7.53-13.01c0.13-0.22,0.33-0.25,0.43-0.25 s0.31,0.03,0.43,0.25l7.53,13.01c0.13,0.22,0.05,0.41,0,0.5c-0.05,0.09-0.18,0.25-0.43,0.25H4.47C4.22,19.5,4.09,19.34,4.04,19.25z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M12,14.75c0.41,0,0.75-0.34,0.75-0.75V9.75C12.75,9.33,12.41,9,12,9s-0.75,0.34-0.75,0.75V14 C11.25,14.41,11.59,14.75,12,14.75z" />
+ android:pathData="M12,14.5c0.41,0,0.75-0.34,0.75-0.75v-4C12.75,9.33,12.41,9,12,9s-0.75,0.34-0.75,0.75v4C11.25,14.16,11.59,14.5,12,14.5z" />
<path
android:fillColor="@android:color/white"
android:pathData="M 12 16 C 12.5522847498 16 13 16.4477152502 13 17 C 13 17.5522847498 12.5522847498 18 12 18 C 11.4477152502 18 11 17.5522847498 11 17 C 11 16.4477152502 11.4477152502 16 12 16 Z" />
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_widget.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_widget.xml
index c3bc349..fcddfc3 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_widget.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_widget.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_arrow_down_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_arrow_down_24dp.xml
new file mode 100644
index 0000000..6419515
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_arrow_down_24dp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19.78,8.22c-0.29-0.29-0.77-0.29-1.06,0L12,14.94L5.28,8.22c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06L12,17.06 l7.78-7.78C20.07,8.99,20.07,8.51,19.78,8.22z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
new file mode 100644
index 0000000..9569e68
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M7.97,20.03c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22L17.06,12L9.03,3.97c-0.29-0.29-0.77-0.29-1.06,0 s-0.29,0.77,0,1.06L14.94,12l-6.97,6.97C7.68,19.26,7.68,19.74,7.97,20.03z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
index 87cdb7b..9dea4ca 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
@@ -23,5 +23,4 @@
<path
android:fillColor="@android:color/white"
android:pathData="M17.5,21.5H4c-0.3,0-0.5-0.2-0.5-0.5V7.5C3.5,7.2,3.3,7,3,7H2.5C2.2,7,2,7.2,2,7.5v14C2,22.3,2.7,23,3.5,23h14 c0.3,0,0.5-0.2,0.5-0.5V22C18,21.7,17.8,21.5,17.5,21.5z M21,16V4c0-1.7-1.4-3-3-3H9C7.3,1,6,2.3,6,4v12c0,1.6,1.3,3,3,3h9 C19.6,19,21,17.6,21,16z M18,17.5H9c-0.8,0-1.5-0.7-1.5-1.5V4c0-0.8,0.7-1.5,1.5-1.5h9c0.8,0,1.5,0.7,1.5,1.5v12 C19.5,16.8,18.8,17.5,18,17.5z" />
- <path android:pathData="M0,0h24v24H0V0z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help_actionbar.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help_actionbar.xml
new file mode 100644
index 0000000..8b388f2
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help_actionbar.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,22c0,0,0.01,0,0.01,0c5.51,0,9.98-4.46,9.99-9.98c0-0.01,0-0.01,0-0.02c0-5.52-4.48-10-10-10S2,6.48,2,12 S6.48,22,12,22z M12,3.5c4.69,0,8.5,3.81,8.5,8.52c-0.01,4.68-3.81,8.48-8.5,8.48c-4.69,0-8.5-3.81-8.5-8.5 C3.5,7.31,7.31,3.5,12,3.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8.57,9.89c0.4,0.1,0.81-0.15,0.9-0.56c0.12-0.5,0.36-0.94,0.71-1.29c1.06-1.06,2.78-1.06,3.84,0 c0.53,0.53,0.79,1.23,0.72,1.92c-0.06,0.62-0.39,1.15-0.92,1.5c-0.17,0.11-0.35,0.19-0.52,0.27c-0.7,0.33-1.67,0.78-1.93,2.37 c-0.07,0.41,0.21,0.8,0.61,0.86C12.02,14.99,12.06,15,12.1,15c0.36,0,0.68-0.26,0.74-0.62c0.14-0.82,0.48-0.98,1.09-1.26 c0.25-0.11,0.49-0.23,0.72-0.38c0.91-0.6,1.48-1.53,1.58-2.61c0.12-1.14-0.31-2.28-1.15-3.13c-1.64-1.64-4.32-1.64-5.96,0 c-0.54,0.54-0.93,1.24-1.11,2C7.92,9.39,8.16,9.8,8.57,9.89z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 16.5 C 12.5522847498 16.5 13 16.9477152502 13 17.5 C 13 18.0522847498 12.5522847498 18.5 12 18.5 C 11.4477152502 18.5 11 18.0522847498 11 17.5 C 11 16.9477152502 11.4477152502 16.5 12 16.5 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_info_outline_24.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_info_outline_24.xml
new file mode 100644
index 0000000..2de16c9
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_info_outline_24.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.99,2C6.47,2,2,6.48,2,12c0,5.52,4.47,10,9.99,10C17.52,22,22,17.52,22,12C22,6.48,17.52,2,11.99,2z M11.99,20.5 c-4.68,0-8.49-3.81-8.49-8.5c0-4.69,3.81-8.5,8.49-8.5c4.69,0,8.51,3.81,8.51,8.5C20.5,16.69,16.68,20.5,11.99,20.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,10.5c-0.41,0-0.75,0.34-0.75,0.75v5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-5 C12.75,10.84,12.41,10.5,12,10.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 7 C 12.5522847498 7 13 7.44771525017 13 8 C 13 8.55228474983 12.5522847498 9 12 9 C 11.4477152502 9 11 8.55228474983 11 8 C 11 7.44771525017 11.4477152502 7 12 7 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_network_cell.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_network_cell.xml
index af4a4aa..b6fa9fc 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_network_cell.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_network_cell.xml
@@ -22,17 +22,14 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M20,4.75C20,4.34,19.66,4,19.25,4S18.5,4.34,18.5,4.75V22H20V4.75z" />
+ android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M15.75,8C15.34,8,15,8.34,15,8.75V22h1.5V8.75C16.5,8.34,16.16,8,15.75,8z" />
+ android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M12.25,12c-0.41,0-0.75,0.34-0.75,0.75V22H13v-9.25C13,12.34,12.66,12,12.25,12z" />
+ android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M8.75,15C8.34,15,8,15.34,8,15.75V22h1.5v-6.25C9.5,15.34,9.16,15,8.75,15z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M5.25,19c-0.41,0-0.75,0.34-0.75,0.75V22H6v-2.25C6,19.34,5.66,19,5.25,19z" />
+ android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_search_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_search_24dp.xml
new file mode 100644
index 0000000..c27e80e
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_search_24dp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9.5,16c1.51,0,2.9-0.52,4.01-1.39l5.47,5.42c0.15,0.15,0.34,0.22,0.53,0.22c0.19,0,0.39-0.07,0.53-0.22 c0.29-0.29,0.29-0.77,0-1.06l-5.46-5.41C15.46,12.45,16,11.04,16,9.5C16,5.91,13.09,3,9.5,3S3,5.91,3,9.5S5.91,16,9.5,16z M9.5,4.5 c2.76,0,5,2.24,5,5s-2.24,5-5,5s-5-2.24-5-5S6.74,4.5,9.5,4.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accent.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accent.xml
new file mode 100644
index 0000000..e10898f
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accent.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorAccent"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,8.5c-1.93,0-3.5,1.57-3.5,3.5s1.57,3.5,3.5,3.5c1.93,0,3.5-1.57,3.5-3.5S13.93,8.5,12,8.5z M12,14c-1.1,0-2-0.9-2-2 s0.9-2,2-2c1.1,0,2,0.9,2,2S13.1,14,12,14z M21.29,13.9l-1.83-1.05c-0.3-0.17-0.49-0.49-0.48-0.84v-0.01 c0-0.35,0.18-0.67,0.48-0.84l1.83-1.05c0.48-0.28,0.64-0.89,0.37-1.37l-2-3.46c-0.19-0.32-0.52-0.5-0.87-0.5 c-0.17,0-0.34,0.04-0.5,0.13l-1.84,1.06c-0.14,0.08-0.29,0.12-0.45,0.12c-0.17,0-0.35-0.05-0.5-0.14c0,0-0.01,0-0.01-0.01 C15.2,5.77,15,5.47,15,5.12V3c0-0.55-0.45-1-1-1h-4C9.45,2,9,2.45,9,3v2.12c0,0.34-0.2,0.65-0.5,0.82c0,0-0.01,0-0.01,0.01 c-0.16,0.09-0.33,0.14-0.5,0.14c-0.15,0-0.31-0.04-0.45-0.12L5.71,4.9c-0.16-0.09-0.33-0.13-0.5-0.13c-0.35,0-0.68,0.18-0.87,0.5 l-2,3.46C2.06,9.21,2.23,9.82,2.71,10.1l1.83,1.05c0.3,0.17,0.49,0.49,0.48,0.84v0.01c0,0.35-0.18,0.67-0.48,0.84L2.71,13.9 c-0.48,0.28-0.64,0.89-0.37,1.37l2,3.46c0.19,0.32,0.52,0.5,0.87,0.5c0.17,0,0.34-0.04,0.5-0.13l1.84-1.06 c0.14-0.08,0.29-0.12,0.45-0.12c0.17,0,0.35,0.05,0.5,0.14c0,0,0.01,0,0.01,0.01C8.8,18.23,9,18.53,9,18.88V21c0,0.55,0.45,1,1,1h4 c0.55,0,1-0.45,1-1v-2.12c0-0.34,0.2-0.65,0.5-0.82c0,0,0.01,0,0.01-0.01c0.16-0.09,0.33-0.14,0.5-0.14c0.15,0,0.31,0.04,0.45,0.12 l1.84,1.06c0.16,0.09,0.33,0.13,0.5,0.13c0.35,0,0.68-0.18,0.87-0.5l2-3.46C21.94,14.79,21.77,14.18,21.29,13.9z M18.61,17.55 l-1.41-0.81c-0.36-0.21-0.78-0.32-1.2-0.32c-0.43,0-0.86,0.12-1.25,0.34c-0.77,0.44-1.25,1.25-1.25,2.12v1.62h-3v-1.62 c0-0.87-0.48-1.68-1.26-2.12c-0.38-0.22-0.81-0.33-1.25-0.33c-0.42,0-0.84,0.11-1.2,0.32l-1.41,0.81l-1.5-2.6l1.39-0.8 c0.76-0.44,1.24-1.26,1.23-2.15c0-0.88-0.47-1.7-1.23-2.14l-1.39-0.8l1.5-2.6L6.8,7.26c0.36,0.21,0.78,0.32,1.2,0.32 c0.43,0,0.86-0.12,1.25-0.34c0.77-0.44,1.25-1.25,1.25-2.12V3.5h3v1.62c0,0.87,0.48,1.68,1.26,2.12c0.38,0.22,0.81,0.33,1.25,0.33 c0.42,0,0.84-0.11,1.2-0.32l1.41-0.81l1.5,2.6l-1.39,0.8c-0.76,0.44-1.24,1.26-1.23,2.15c0,0.88,0.47,1.7,1.23,2.14l1.39,0.8 L18.61,17.55z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_backup.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_backup.xml
new file mode 100644
index 0000000..b46a7f1
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_backup.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M7.75,19H22v-4.5c0-2.34-1.79-4.27-4.08-4.48C17.45,7.18,14.97,5,12,5C9.82,5,7.83,6.18,6.78,8.06 c-2.97,0.39-5.21,3.19-4.71,6.31C2.5,17.09,5,19,7.75,19z M4.29,11.13c0.65-0.87,1.63-1.45,2.68-1.58l0.75-0.1l0.37-0.66 C8.88,7.38,10.38,6.5,12,6.5c2.18,0,4.08,1.62,4.44,3.76l0.19,1.14l1.15,0.11c1.52,0.14,2.72,1.45,2.72,2.99v3H7.75 c-2.09,0-3.9-1.45-4.2-3.36C3.38,13.07,3.64,12,4.29,11.13z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9.95,13.1l1.3-1.3v3.45c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75V11.8l1.3,1.3c0.15,0.15,0.34,0.22,0.53,0.22 s0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06L12,8.93l-3.11,3.11c-0.29,0.29-0.29,0.77,0,1.06S9.66,13.39,9.95,13.1z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_storage.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_storage.xml
new file mode 100644
index 0000000..5d66692
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_storage.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21,17c0-1.1-0.9-2-2-2H5c-1.1,0-2,0.9-2,2v3h18V17z M19.5,18.5h-15V17c0-0.28,0.22-0.5,0.5-0.5h14 c0.28,0,0.5,0.22,0.5,0.5V18.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21,5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v3h18V5z M19.5,6.5h-15V5c0-0.28,0.22-0.5,0.5-0.5h14c0.28,0,0.5,0.22,0.5,0.5V6.5 z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21,11c0-1.1-0.9-2-2-2H5c-1.1,0-2,0.9-2,2v3h18V11z M19.5,12.5h-15V11c0-0.28,0.22-0.5,0.5-0.5h14 c0.28,0,0.5,0.22,0.5,0.5V12.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 6.01 4.75 C 6.42421356237 4.75 6.76 5.08578643763 6.76 5.5 C 6.76 5.91421356237 6.42421356237 6.25 6.01 6.25 C 5.59578643763 6.25 5.26 5.91421356237 5.26 5.5 C 5.26 5.08578643763 5.59578643763 4.75 6.01 4.75 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 6.01 10.75 C 6.42421356237 10.75 6.76 11.0857864376 6.76 11.5 C 6.76 11.9142135624 6.42421356237 12.25 6.01 12.25 C 5.59578643763 12.25 5.26 11.9142135624 5.26 11.5 C 5.26 11.0857864376 5.59578643763 10.75 6.01 10.75 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 6.01 16.75 C 6.42421356237 16.75 6.76 17.0857864376 6.76 17.5 C 6.76 17.9142135624 6.42421356237 18.25 6.01 18.25 C 5.59578643763 18.25 5.26 17.9142135624 5.26 17.5 C 5.26 17.0857864376 5.59578643763 16.75 6.01 16.75 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_sync.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_sync.xml
new file mode 100644
index 0000000..e8f5e86
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_sync.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,12c0-2.13-0.83-4.13-2.34-5.64c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06c1.23,1.22,1.9,2.85,1.9,4.58 c0,3.57-2.92,6.48-6.5,6.48c-0.43,0-0.86-0.06-1.28-0.14l1.31-1.31c0.29-0.29,0.29-0.77,0-1.06c-0.29-0.29-0.77-0.29-1.06,0 L7.94,19l3.03,3.03c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06l-1.07-1.07 c0.34,0.04,0.69,0.07,1.04,0.07C16.41,19.98,20,16.4,20,12z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M5.5,12c0-3.57,2.92-6.48,6.5-6.48c0.43,0,0.86,0.06,1.28,0.14l-1.31,1.31c-0.29,0.29-0.29,0.77,0,1.06 c0.15,0.15,0.34,0.22,0.53,0.22c0.19,0,0.38-0.07,0.53-0.22L16.06,5l-3.03-3.03c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06 l1.07,1.07C12.69,4.05,12.35,4.02,12,4.02C7.59,4.02,4,7.6,4,12c0,2.13,0.83,4.13,2.34,5.64c0.15,0.15,0.34,0.22,0.53,0.22 c0.19,0,0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06C6.18,15.35,5.5,13.73,5.5,12z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_system_update.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_system_update.xml
new file mode 100644
index 0000000..c2fd678
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_system_update.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,5v14c0,1.66,1.34,3,3,3h6c1.66,0,3-1.34,3-3V5c0-1.66-1.34-3-3-3H9C7.34,2,6,3.34,6,5z M16.5,17.5h-9v-11h9V17.5z M15,20.5H9c-0.83,0-1.5-0.67-1.5-1.5h9C16.5,19.83,15.83,20.5,15,20.5z M9,3.5h6c0.83,0,1.5,0.67,1.5,1.5h-9 C7.5,4.17,8.17,3.5,9,3.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8.47,13.03L12,16.56l3.53-3.53c0.29-0.29,0.29-0.77,0-1.06s-0.77-0.29-1.06,0l-1.72,1.72V8.75C12.75,8.34,12.41,8,12,8 s-0.75,0.34-0.75,0.75v4.94l-1.72-1.72c-0.29-0.29-0.77-0.29-1.06,0S8.18,12.74,8.47,13.03z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_arrow_back.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_arrow_back.xml
new file mode 100644
index 0000000..920ecb5
--- /dev/null
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_arrow_back.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,11.25H5.81l6.22-6.22c0.29-0.29,0.29-0.77,0-1.06s-0.77-0.29-1.06,0L2.94,12l8.03,8.03 c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06l-6.22-6.22h14.44c0.41,0,0.75-0.34,0.75-0.75 S20.66,11.25,20.25,11.25z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_cast.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_cast.xml
index ff20e48..05b490f 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_cast.xml
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_cast.xml
@@ -15,10 +15,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
+ android:height="17dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="24dp" >
+ android:width="17dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M2.25,9C2.66,9,3,8.66,3,8.25v-1C3,6.01,4.01,5,5.25,5h13.5C19.99,5,21,6.01,21,7.25V19h-7.25C13.34,19,13,19.34,13,19.75 s0.34,0.75,0.75,0.75h8.75V7.25c0-2.07-1.68-3.75-3.75-3.75H5.25C3.18,3.5,1.5,5.18,1.5,7.25v1C1.5,8.66,1.84,9,2.25,9z" />
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_cast_connected.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_cast_connected.xml
index cc181a3..a7547db 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_cast_connected.xml
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_cast_connected.xml
@@ -15,10 +15,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="17dp"
+ android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="17dp" >
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M2.25,9C2.66,9,3,8.66,3,8.25v-1C3,6.01,4.01,5,5.25,5h13.5C19.99,5,21,6.01,21,7.25V19h-7.25C13.34,19,13,19.34,13,19.75 s0.34,0.75,0.75,0.75h8.75V7.25c0-2.07-1.68-3.75-3.75-3.75H5.25C3.18,3.5,1.5,5.18,1.5,7.25v1C1.5,8.66,1.84,9,2.25,9z" />
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_cast_connected_fill.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_cast_connected_fill.xml
new file mode 100644
index 0000000..18f81e7
--- /dev/null
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_cast_connected_fill.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="17dp"
+ android:tint="?android:attr/colorError"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="17dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M13.75,15C13.34,15,13,15.34,13,15.75s0.34,0.75,0.75,0.75h4c0.41,0,0.75-0.34,0.75-0.75v-6.5c0-0.96-0.79-1.75-1.75-1.75 H6.25C5.84,7.5,5.5,7.84,5.5,8.25S5.84,9,6.25,9h10.5C16.89,9,17,9.11,17,9.25V15H13.75z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_headset_mic.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_headset_mic.xml
index a50d431..bbbebb5 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_headset_mic.xml
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_headset_mic.xml
@@ -19,7 +19,6 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="17dp" >
- <path android:pathData="M0,0h24v24H0V0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M12,1c-4.96,0-9,4.04-9,9v6.78C3,18.56,4.41,20,6.13,20H9v-8H4.5v-2c0-4.13,3.36-7.5,7.5-7.5s7.5,3.36,7.5,7.5v2H15v8h2.87 c0.59,0,1.13-0.18,1.6-0.47c-0.14,1.11-1.08,1.97-2.22,1.97h-4.5c-0.41,0-0.75,0.34-0.75,0.75S12.34,23,12.75,23h4.5 c2.07,0,3.75-1.68,3.75-3.75V10C21,5.04,16.96,1,12,1z M7.5,18.5H6.13c-0.9,0-1.63-0.77-1.63-1.72V13.5h3V18.5z M17.87,18.5H16.5 v-5h3V16v0.78C19.5,17.73,18.77,18.5,17.87,18.5z" />
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/stat_sys_managed_profile_status.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/stat_sys_managed_profile_status.xml
new file mode 100644
index 0000000..488d15a
--- /dev/null
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/stat_sys_managed_profile_status.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="17dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="17dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M16,4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H2v12c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V6h-6V4z M9.5,4 c0-0.3,0.2-0.5,0.5-0.5h4c0.3,0,0.5,0.2,0.5,0.5v2h-5V4z M20.5,7.5V18c0,0.8-0.7,1.5-1.5,1.5H5c-0.8,0-1.5-0.7-1.5-1.5V7.5H20.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 12.3 C 12.6627416998 12.3 13.2 12.8372583002 13.2 13.5 C 13.2 14.1627416998 12.6627416998 14.7 12 14.7 C 11.3372583002 14.7 10.8 14.1627416998 10.8 13.5 C 10.8 12.8372583002 11.3372583002 12.3 12 12.3 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/Android.mk b/packages/overlays/IconPackCircularThemePickerOverlay/Android.mk
new file mode 100644
index 0000000..412c26f
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/Android.mk
@@ -0,0 +1,31 @@
+#
+# Copyright 2019, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := IconPackCircularThemePicker
+LOCAL_CERTIFICATE := platform
+LOCAL_PRODUCT_MODULE := true
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := IconPackCircularThemePickerOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/AndroidManifest.xml b/packages/overlays/IconPackCircularThemePickerOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..eae7de8
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.theme.icon_pack.circular.themepicker"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="com.android.wallpaper" android:category="android.theme.customization.icon_pack.themepicker" android:priority="1"/>
+ <application android:label="Circular" android:hasCode="false"/>
+</manifest>
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_add_24px.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_add_24px.xml
new file mode 100644
index 0000000..900aaa0
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_add_24px.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,11.25h-7.5v-7.5C12.75,3.34,12.41,3,12,3s-0.75,0.34-0.75,0.75v7.5h-7.5C3.34,11.25,3,11.59,3,12 s0.34,0.75,0.75,0.75h7.5v7.5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-7.5h7.5c0.41,0,0.75-0.34,0.75-0.75 S20.66,11.25,20.25,11.25z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_close_24px.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_close_24px.xml
new file mode 100644
index 0000000..ddfb980
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_close_24px.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.03,3.97c-0.29-0.29-0.77-0.29-1.06,0L12,10.94L5.03,3.97c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06L10.94,12 l-6.97,6.97c-0.29,0.29-0.29,0.77,0,1.06c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22L12,13.06l6.97,6.97 c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06L13.06,12l6.97-6.97 C20.32,4.74,20.32,4.26,20.03,3.97z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_colorize_24px.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_colorize_24px.xml
new file mode 100644
index 0000000..f572af6
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_colorize_24px.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M17.59,3.59l-2.97,2.97l-2.09-2.09c-0.29-0.29-0.77-0.29-1.06,0c-0.29,0.29-0.29,0.77,0,1.06l1.5,1.5l-9.68,9.68 C3.11,16.89,3,17.15,3,17.41V21h3.59c0.27,0,0.52-0.11,0.71-0.29l9.68-9.68l1.5,1.5c0.15,0.15,0.34,0.22,0.53,0.22 c0.19,0,0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06l-2.09-2.09l2.97-2.97c0.78-0.78,0.78-2.05,0-2.83 C19.63,2.8,18.37,2.8,17.59,3.59z M6.38,19.5H4.5v-1.88l9.5-9.5L15.88,10L6.38,19.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_delete_24px.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_delete_24px.xml
new file mode 100644
index 0000000..a87186b
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_delete_24px.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9,20h6c1.66,0,3-1.34,3-3V6h0.5c0.41,0,0.75-0.34,0.75-0.75S18.91,4.5,18.5,4.5H18h-3l-1-1h-4l-1,1H6H5.5 c-0.41,0-0.75,0.34-0.75,0.75S5.09,6,5.5,6H6v11C6,18.66,7.34,20,9,20z M16.5,6v11c0,0.83-0.67,1.5-1.5,1.5H9 c-0.83,0-1.5-0.67-1.5-1.5V6H16.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M13.97,16c0.41,0,0.75-0.34,0.75-0.75v-6.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v6.5 C13.22,15.66,13.55,16,13.97,16z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10,16c0.41,0,0.75-0.34,0.75-0.75v-6.5C10.75,8.34,10.41,8,10,8S9.25,8.34,9.25,8.75v6.5C9.25,15.66,9.59,16,10,16z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_font.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_font.xml
new file mode 100644
index 0000000..edaf3c7
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_font.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18,2H6C3.8,2,2,3.8,2,6v12c0,2.2,1.8,4,4,4h12c2.2,0,4-1.8,4-4V6C22,3.8,20.2,2,18,2z M20.5,18c0,1.38-1.12,2.5-2.5,2.5H6 c-1.38,0-2.5-1.12-2.5-2.5V6c0-1.38,1.12-2.5,2.5-2.5h12c1.38,0,2.5,1.12,2.5,2.5V18z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10.69,6L6.2,18h2.5l1-2.87h4.59L15.3,18h2.5L13.29,6H10.69z M10.43,13.06l1.51-4.46h0.13l1.49,4.46H10.43z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_clock.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_clock.xml
new file mode 100644
index 0000000..2884d71
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_clock.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,12c0-5.52-4.48-10-10-10C6.48,2,2,6.48,2,12s4.48,10,10,10C17.52,22,22,17.52,22,12z M12,20.5 c-4.69,0-8.5-3.81-8.5-8.5S7.31,3.5,12,3.5c4.69,0,8.5,3.81,8.5,8.5S16.69,20.5,12,20.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12.75,11.69V5.78c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v6.53l3.78,3.78c0.15,0.15,0.34,0.22,0.53,0.22 s0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06L12.75,11.69z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_grid.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_grid.xml
new file mode 100644
index 0000000..d50dbd4
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_grid.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M2.75,16.75C2.34,16.75,2,17.09,2,17.5s0.34,0.75,0.75,0.75h3v3C5.75,21.66,6.09,22,6.5,22s0.75-0.34,0.75-0.75v-3h4v3 c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-3h4v3c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-3h3 c0.41,0,0.75-0.34,0.75-0.75s-0.34-0.75-0.75-0.75h-3v-4h3c0.41,0,0.75-0.34,0.75-0.75s-0.34-0.75-0.75-0.75h-3v-4h3 C21.66,7.25,22,6.91,22,6.5s-0.34-0.75-0.75-0.75h-3v-3C18.25,2.34,17.91,2,17.5,2s-0.75,0.34-0.75,0.75v3h-4v-3 C12.75,2.34,12.41,2,12,2s-0.75,0.34-0.75,0.75v3h-4v-3C7.25,2.34,6.91,2,6.5,2S5.75,2.34,5.75,2.75v3h-3C2.34,5.75,2,6.09,2,6.5 s0.34,0.75,0.75,0.75h3v4h-3C2.34,11.25,2,11.59,2,12s0.34,0.75,0.75,0.75h3v4H2.75z M16.75,16.75h-4v-4h4V16.75z M16.75,7.25v4h-4 v-4H16.75z M7.25,7.25h4v4h-4V7.25z M7.25,12.75h4v4h-4V12.75z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_theme.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_theme.xml
new file mode 100644
index 0000000..7375bc9
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_theme.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8,14h1v5c0,1.66,1.34,3,3,3s3-1.34,3-3v-5h1c1.66,0,3-1.34,3-3V2H5v9C5,12.66,6.34,14,8,14z M16,12.5h-2.5V14v5 c0,0.83-0.67,1.5-1.5,1.5s-1.5-0.67-1.5-1.5v-5v-1.5H8c-0.83,0-1.5-0.67-1.5-1.5v-0.5h11V11C17.5,11.83,16.83,12.5,16,12.5z M9,3.5 v3c0,0.41,0.34,0.75,0.75,0.75S10.5,6.91,10.5,6.5v-3h2.75v3c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-3h2.75V9h-11V3.5H9z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_wallpaper.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_wallpaper.xml
new file mode 100644
index 0000000..bdb7442
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_nav_wallpaper.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 16 6.75 C 16.6903559373 6.75 17.25 7.30964406271 17.25 8 C 17.25 8.69035593729 16.6903559373 9.25 16 9.25 C 15.3096440627 9.25 14.75 8.69035593729 14.75 8 C 14.75 7.30964406271 15.3096440627 6.75 16 6.75 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11,3.76c0-0.41-0.34-0.75-0.75-0.75H6.84C4.72,3.01,3,4.74,3,6.85v3.4C3,10.66,3.34,11,3.75,11s0.75-0.34,0.75-0.75v-3.4 c0-1.29,1.05-2.33,2.34-2.33h3.41C10.66,4.51,11,4.18,11,3.76z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10.25,19.5H6.84c-1.29,0-2.34-1.05-2.34-2.34v-3.41C4.5,13.34,4.16,13,3.75,13S3,13.34,3,13.75v3.41 C3,19.28,4.72,21,6.84,21h3.41c0.41,0,0.75-0.34,0.75-0.75S10.66,19.5,10.25,19.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,13c-0.41,0-0.75,0.34-0.75,0.75v3.41c0,1.29-1.05,2.34-2.34,2.34h-3.41c-0.41,0-0.75,0.34-0.75,0.75 S13.34,21,13.75,21h3.41c2.12,0,3.84-1.72,3.84-3.84v-3.41C21,13.34,20.66,13,20.25,13z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M17.16,3h-3.41C13.34,3,13,3.34,13,3.75s0.34,0.75,0.75,0.75h3.41c1.29,0,2.34,1.05,2.34,2.34v3.41 c0,0.41,0.34,0.75,0.75,0.75S21,10.66,21,10.25V6.84C21,4.72,19.28,3,17.16,3z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12.89,15.29l-1.41-1.82c-0.8-1.04-2.37-1.03-3.17,0.01l-2.7,3.51l12.83-0.01l-1.88-2.35c-0.79-0.99-2.29-1-3.1-0.03 L12.89,15.29z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_shapes_24px.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_shapes_24px.xml
new file mode 100644
index 0000000..b7e6bf9
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_shapes_24px.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,9h-1.5v1.5H19c0.83,0,1.5,0.67,1.5,1.5v7c0,0.83-0.67,1.5-1.5,1.5h-8c-0.83,0-1.5-0.67-1.5-1.5v-1.5H8V19 c0,1.66,1.34,3,3,3h8c1.66,0,3-1.34,3-3v-7C22,10.34,20.66,9,19,9z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9,16c3.87,0,7-3.13,7-7c0-3.87-3.13-7-7-7C5.13,2,2,5.13,2,9C2,12.87,5.13,16,9,16z M3.5,9c0-3.03,2.47-5.5,5.5-5.5 s5.5,2.47,5.5,5.5s-2.47,5.5-5.5,5.5S3.5,12.03,3.5,9z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_tune.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_tune.xml
new file mode 100644
index 0000000..9c88211
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_tune.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="20dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="20dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,4.75h-2.4C17.55,4.02,16.84,3.5,16,3.5c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2c0.84,0,1.55-0.52,1.85-1.25h2.4 C20.66,6.25,21,5.91,21,5.5S20.66,4.75,20.25,4.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.98,4.75H3.75C3.34,4.75,3,5.09,3,5.5s0.34,0.75,0.75,0.75h8.23c0.01,0,0.01,0,0.02,0V4.75 C11.99,4.75,11.99,4.75,11.98,4.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,17.75h-5.4c-0.3-0.73-1.01-1.25-1.85-1.25c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2c0.84,0,1.55-0.52,1.85-1.25h5.4 c0.41,0,0.75-0.34,0.75-0.75S20.66,17.75,20.25,17.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8.98,17.75H3.75C3.34,17.75,3,18.09,3,18.5s0.34,0.75,0.75,0.75h5.23c0.01,0,0.01,0,0.02,0v-1.49 C8.99,17.75,8.99,17.75,8.98,17.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M7,10c-0.84,0-1.55,0.52-1.85,1.25h-1.4C3.34,11.25,3,11.59,3,12s0.34,0.75,0.75,0.75h1.4C5.45,13.48,6.16,14,7,14 c1.1,0,2-0.9,2-2C9,10.9,8.1,10,7,10z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,11.25h-9.23c-0.01,0-0.01,0-0.02,0v1.49c0.01,0,0.01,0,0.02,0h9.23c0.41,0,0.75-0.34,0.75-0.75 S20.66,11.25,20.25,11.25z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_wifi_24px.xml b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_wifi_24px.xml
new file mode 100644
index 0000000..fde9965
--- /dev/null
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/res/drawable/ic_wifi_24px.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 17 C 12.8284271247 17 13.5 17.6715728753 13.5 18.5 C 13.5 19.3284271247 12.8284271247 20 12 20 C 11.1715728753 20 10.5 19.3284271247 10.5 18.5 C 10.5 17.6715728753 11.1715728753 17 12 17 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19.42,11.84c-0.19,0-0.38-0.07-0.53-0.22C17.05,9.77,14.6,8.75,12,8.75s-5.05,1.02-6.89,2.86 c-0.29,0.29-0.77,0.29-1.06,0c-0.29-0.29-0.29-0.77,0-1.06C6.17,8.43,9,7.25,12,7.25s5.83,1.17,7.95,3.3 c0.29,0.29,0.29,0.77,0,1.06C19.8,11.76,19.61,11.84,19.42,11.84z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22.61,8.65c-0.19,0-0.38-0.07-0.53-0.22C19.38,5.74,15.81,4.25,12,4.25S4.62,5.74,1.92,8.43c-0.29,0.29-0.77,0.29-1.06,0 s-0.29-0.77,0-1.06C3.84,4.39,7.79,2.75,12,2.75s8.16,1.64,11.14,4.61c0.29,0.29,0.29,0.77,0,1.06 C22.99,8.57,22.8,8.65,22.61,8.65z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M16.25,15c-0.19,0-0.38-0.07-0.53-0.22c-1-0.99-2.32-1.53-3.73-1.53s-2.73,0.54-3.73,1.53c-0.29,0.29-0.77,0.29-1.06-0.01 s-0.29-0.77,0.01-1.06c1.28-1.27,2.98-1.96,4.78-1.96s3.5,0.7,4.78,1.96c0.29,0.29,0.3,0.77,0.01,1.06 C16.64,14.93,16.45,15,16.25,15z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml
new file mode 100644
index 0000000..bd5aefa
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@*android:drawable/ic_bluetooth_transient_animation_drawable" >
+ <target
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:animation="@*android:anim/ic_bluetooth_transient_animation_0" />
+ <target
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:animation="@*android:anim/ic_bluetooth_transient_animation_1" />
+ <target
+ android:name="time_group"
+ android:animation="@*android:anim/ic_bluetooth_transient_animation_2" />
+</animated-vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bluetooth_transient_animation_drawable.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bluetooth_transient_animation_drawable.xml
new file mode 100644
index 0000000..4b98a0f
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bluetooth_transient_animation_drawable.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:translateX="3.099"
+ android:translateY="1.6400000000000006" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M10.41 10.36 C10.41,10.36 14.16,6.62 14.16,6.62 C14.57,6.21 14.57,5.55 14.16,5.14 C14.16,5.14 9.69,0.67 9.69,0.67 C9.69,0.67 9.66,0.64 9.66,0.64 C9.24,0.25 8.58,0.27 8.18,0.69 C8,0.88 7.9,1.14 7.9,1.4 C7.9,1.4 7.9,7.84 7.9,7.84 C7.9,7.84 3.85,3.79 3.85,3.79 C3.44,3.38 2.79,3.38 2.38,3.79 C1.97,4.2 1.97,4.85 2.38,5.26 C2.38,5.26 7.47,10.36 7.47,10.36 C7.47,10.36 2.38,15.45 2.38,15.45 C1.97,15.86 1.97,16.51 2.38,16.92 C2.79,17.33 3.44,17.33 3.85,16.92 C3.85,16.92 7.9,12.87 7.9,12.87 C7.9,12.87 7.9,19.32 7.9,19.32 C7.9,19.89 8.37,20.36 8.94,20.36 C9.2,20.36 9.46,20.26 9.65,20.08 C9.65,20.08 9.7,20.03 9.7,20.03 C9.7,20.03 14.16,15.57 14.16,15.57 C14.57,15.16 14.57,14.5 14.16,14.09 C14.16,14.09 10.41,10.36 10.41,10.36c M9.89 3.73 C9.89,3.73 12.04,5.88 12.04,5.88 C12.04,5.88 9.89,8.03 9.89,8.03 C9.89,8.03 9.89,3.73 9.89,3.73c M9.89 16.98 C9.89,16.98 9.89,12.68 9.89,12.68 C9.89,12.68 12.04,14.83 12.04,14.83 C12.04,14.83 9.89,16.98 9.89,16.98c " />
+ </group>
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="3.099"
+ android:translateY="1.6400000000000006" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M16.96 9.3 C16.95,9.3 16.95,9.29 16.95,9.28 C16.36,8.71 15.42,8.72 14.84,9.3 C14.84,9.3 14.83,9.31 14.83,9.31 C14.25,9.9 14.25,10.84 14.84,11.42 C15.42,12.01 16.37,12.01 16.96,11.42 C17.55,10.84 17.55,9.89 16.96,9.3c " />
+ </group>
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="3.099"
+ android:translateY="1.6400000000000006" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M2.96 9.3 C2.96,9.3 2.95,9.29 2.95,9.29 C2.36,8.71 1.42,8.71 0.84,9.3 C0.84,9.3 0.83,9.31 0.83,9.31 C0.25,9.9 0.25,10.84 0.84,11.42 C1.42,12.01 2.37,12.01 2.96,11.42 C3.55,10.83 3.55,9.89 2.96,9.3c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+</vector>
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_headset_hfp.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_headset_hfp.xml
index 0a50050..26527ea 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_headset_hfp.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_headset_hfp.xml
@@ -20,7 +20,6 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path android:pathData="M0,0h24v24H0V0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M11.4,1.02C6.62,1.33,3,5.52,3,10.31L3,17c0,1.66,1.34,3,3,3h2c0.55,0,1-0.45,1-1v-6c0-0.55-0.45-1-1-1H5l0-1.71 C5,6.45,7.96,3.11,11.79,3C15.76,2.89,19,6.06,19,10v2h-3c-0.55,0-1,0.45-1,1v6c0,0.55,0.45,1,1,1h3v1h-6c-0.55,0-1,0.45-1,1v0 c0,0.55,0.45,1,1,1h5c1.66,0,3-1.34,3-3V10C21,4.83,16.64,0.68,11.4,1.02z" />
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_hearing_aid.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_hearing_aid.xml
index aeee379..562ed17 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_hearing_aid.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_hearing_aid.xml
@@ -19,7 +19,6 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path android:pathData="M0,0h24v24H0V0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M17,20c-0.29,0-0.56-0.06-0.76-0.15c-0.71-0.37-1.21-0.88-1.71-2.38c-0.51-1.56-1.47-2.29-2.39-3 c-0.79-0.61-1.61-1.24-2.32-2.53C9.29,10.98,9,9.93,9,9c0-2.8,2.2-5,5-5c2.52,0,4.55,1.78,4.94,4.18C19.01,8.65,19.42,9,19.9,9 h0.04c0.59,0,1.07-0.53,0.98-1.11C20.4,4.51,17.55,2,14,2c-3.93,0-7,3.07-7,7c0,1.26,0.38,2.65,1.07,3.9 c0.91,1.65,1.98,2.48,2.85,3.15c0.81,0.62,1.39,1.07,1.71,2.05c0.6,1.82,1.37,2.84,2.73,3.55C15.87,21.88,16.43,22,17,22 c1.77,0,3.27-1.15,3.8-2.74C21,18.64,20.51,18,19.85,18H19.7c-0.38,0-0.68,0.27-0.81,0.63C18.63,19.42,17.88,20,17,20z M6.98,1.98 L6.95,1.95c-0.42-0.42-1.1-0.37-1.47,0.08C3.93,3.93,3,6.36,3,9s0.93,5.07,2.48,6.97c0.37,0.45,1.06,0.5,1.47,0.08l0.02-0.02 c0.35-0.35,0.39-0.92,0.07-1.3C5.77,13.17,5,11.18,5,9c0-2.17,0.77-4.17,2.05-5.71C7.37,2.9,7.33,2.33,6.98,1.98z M11.5,9 c0,1.38,1.12,2.5,2.5,2.5s2.5-1.12,2.5-2.5S15.38,6.5,14,6.5S11.5,7.62,11.5,9z" />
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_network_pan.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_network_pan.xml
index 5da29704..59a18ba 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_network_pan.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_network_pan.xml
@@ -22,11 +22,11 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
+ android:pathData="M14.95,11.3c-0.39,0.39-0.39,1.03,0,1.42l1.61,1.61C16.84,13.61,17,12.82,17,12s-0.16-1.59-0.43-2.31L14.95,11.3z" />
+ <path
+ android:fillColor="@android:color/white"
android:pathData="M11.51,12l3.75-3.73c0.41-0.41,0.41-1.07,0-1.48l-4.47-4.47l-0.03-0.03C10.57,2.11,10.32,2,10.04,2C9.47,2,9,2.47,9,3.04 v6.45L4.95,5.43c-0.41-0.41-1.06-0.41-1.47,0c-0.41,0.41-0.41,1.06,0,1.47L8.57,12l-5.09,5.09c-0.41,0.41-0.41,1.06,0,1.47 c0.41,0.41,1.06,0.41,1.47,0L9,14.51v6.45C9,21.53,9.47,22,10.04,22c0.28,0,0.53-0.11,0.71-0.27l0.05-0.05l4.46-4.46 c0.41-0.41,0.41-1.07,0-1.48L11.51,12z M10.99,5.38l2.15,2.15l-2.15,2.15V5.38z M10.99,18.62v-4.3l2.15,2.15L10.99,18.62z" />
<path
android:fillColor="@android:color/white"
android:pathData="M20.08,7.77c-0.24-0.54-0.96-0.66-1.39-0.23c-0.26,0.26-0.32,0.65-0.17,0.98c0.47,1.07,0.72,2.24,0.72,3.47 c0,1.24-0.26,2.43-0.73,3.49c-0.14,0.32-0.09,0.69,0.16,0.94c0.4,0.4,1.09,0.29,1.34-0.23c0.63-1.3,0.98-2.76,0.98-4.3 C20.98,10.43,20.66,9.03,20.08,7.77z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M14.95,11.3c-0.39,0.39-0.39,1.03,0,1.42l1.61,1.61C16.84,13.61,17,12.82,17,12s-0.16-1.59-0.43-2.31L14.95,11.3z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_pointing_hid.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_pointing_hid.xml
index e13b90f..a05cf65 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_pointing_hid.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_pointing_hid.xml
@@ -20,7 +20,6 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path android:pathData="M0,0h24v24H0V0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M13,1.07V9h7C20,4.92,16.95,1.56,13,1.07z M4,15c0,4.42,3.58,8,8,8s8-3.58,8-8v-4H4V15z M11,1.07C7.05,1.56,4,4.92,4,9h7 V1.07z" />
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_corp_badge.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_corp_badge.xml
new file mode 100644
index 0000000..1eba6a4
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_corp_badge.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="@*android:color/accent_device_default_light"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path android:pathData="M 10 4 H 14 V 6 H 10 V 4 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,6h-4V4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8 C22,6.9,21.1,6,20,6z M12,15c-0.8,0-1.5-0.7-1.5-1.5S11.2,12,12,12s1.5,0.7,1.5,1.5S12.8,15,12,15z M14,6h-4V4h4V6z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_expand_more.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_expand_more.xml
index 3a52b87..82436f5 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_expand_more.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_expand_more.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml
new file mode 100644
index 0000000..eb23452
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@*android:drawable/ic_hotspot_transient_animation_drawable" >
+ <target
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_2" />
+ <target
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_1" />
+ <target
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_0" />
+ <target
+ android:name="time_group"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_3" />
+</animated-vector>
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_hotspot_transient_animation_drawable.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_hotspot_transient_animation_drawable.xml
new file mode 100644
index 0000000..3171262
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_hotspot_transient_animation_drawable.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="1.545"
+ android:translateY="2.1449999999999996" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M9.31 0.92 C4.67,1.43 0.92,5.26 0.5,9.92 C0.25,12.64 1.1,15.17 2.65,17.1 C3.02,17.56 3.71,17.6 4.13,17.18 C4.49,16.82 4.52,16.25 4.21,15.86 C2.81,14.11 2.12,11.76 2.61,9.25 C3.22,6.12 5.75,3.6 8.89,3 C14,2.04 18.45,5.92 18.45,10.86 C18.45,12.75 17.79,14.48 16.69,15.86 C16.37,16.25 16.41,16.81 16.77,17.17 C16.77,17.17 16.77,17.17 16.77,17.17 C17.19,17.59 17.89,17.56 18.26,17.09 C19.64,15.39 20.45,13.22 20.45,10.86 C20.45,4.96 15.34,0.25 9.31,0.92c " />
+ <path
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M13.91 14.31 C13.91,14.31 13.92,14.32 13.92,14.32 C14.35,14.75 15.08,14.71 15.42,14.21 C16.07,13.25 16.45,12.1 16.45,10.85 C16.45,7.11 13.01,4.16 9.12,5 C6.88,5.49 5.08,7.3 4.6,9.54 C4.22,11.28 4.61,12.92 5.48,14.2 C5.83,14.71 6.56,14.75 6.99,14.32 C6.99,14.32 7,14.31 7,14.31 C7.34,13.97 7.37,13.43 7.1,13.03 C6.6,12.26 6.36,11.32 6.49,10.29 C6.73,8.55 8.16,7.13 9.9,6.89 C12.36,6.56 14.46,8.46 14.46,10.85 C14.46,11.66 14.22,12.4 13.81,13.02 C13.54,13.43 13.57,13.97 13.91,14.31c " />
+ <path
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M12.46 10.86 C12.46,11.96 11.56,12.86 10.46,12.86 C9.35,12.86 8.46,11.96 8.46,10.86 C8.46,9.75 9.35,8.86 10.46,8.86 C11.56,8.86 12.46,9.75 12.46,10.86c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+</vector>
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_battery_saver.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
new file mode 100644
index 0000000..22e183c
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10,2v2H8.33C7.6,4,7,4.6,7,5.33v15.33C7,21.4,7.6,22,8.33,22h7.33C16.4,22,17,21.4,17,20.67V5.33C17,4.6,16.4,4,15.67,4 H14V2H10z M15,13c0,0.55-0.45,1-1,1h-1v1c0,0.55-0.45,1-1,1s-1-0.45-1-1v-1h-1c-0.55,0-1-0.45-1-1s0.45-1,1-1h1v-1 c0-0.55,0.45-1,1-1s1,0.45,1,1v1h1C14.55,12,15,12.45,15,13z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml
new file mode 100644
index 0000000..560309e
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M3.8,22h17.19c0.55,0,1.01-0.45,1.01-1.01V3.8c0-0.71-0.87-1.08-1.38-0.57L3.24,20.62C2.73,21.13,3.09,22,3.8,22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_0_5_bar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_0_5_bar.xml
new file mode 100644
index 0000000..560309e
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_0_5_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M3.8,22h17.19c0.55,0,1.01-0.45,1.01-1.01V3.8c0-0.71-0.87-1.08-1.38-0.57L3.24,20.62C2.73,21.13,3.09,22,3.8,22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml
new file mode 100644
index 0000000..6f6ecaf
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M3.8,22h17.19c0.55,0,1.01-0.45,1.01-1.01V3.8c0-0.71-0.87-1.08-1.38-0.57L3.24,20.62C2.73,21.13,3.09,22,3.8,22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.93,11.93l-8.69,8.69C2.73,21.13,3.09,22,3.8,22h8.13V11.93z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_1_5_bar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_1_5_bar.xml
new file mode 100644
index 0000000..f986c48
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_1_5_bar.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M3.8,22H21a1,1,0,0,0,1-1V3.8a0.81 0.81 ,0,0,0-1.38-0.57L3.24,20.62A0.81 0.81 ,0,0,0,3.8,22Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.24,20.62A0.81 0.81 ,0,0,0,3.8,22H7.93V15.93Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml
new file mode 100644
index 0000000..876cd032
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M3.8,22h17.19c0.55,0,1.01-0.45,1.01-1.01V3.8c0-0.71-0.87-1.08-1.38-0.57L3.24,20.62C2.73,21.13,3.09,22,3.8,22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M13.94,9.92l-10.7,10.7C2.73,21.13,3.09,22,3.8,22h10.14L13.94,9.92z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_2_5_bar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_2_5_bar.xml
new file mode 100644
index 0000000..d6b61c8
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_2_5_bar.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M3.8,22H21a1,1,0,0,0,1-1V3.8a0.81 0.81 ,0,0,0-1.38-0.57L3.24,20.62A0.81 0.81 ,0,0,0,3.8,22Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.24,20.62A0.81 0.81 ,0,0,0,3.8,22h7.65V12.41Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml
new file mode 100644
index 0000000..883740f
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M3.8,22h17.19c0.55,0,1.01-0.45,1.01-1.01V3.8c0-0.71-0.87-1.08-1.38-0.57L3.24,20.62C2.73,21.13,3.09,22,3.8,22z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M16.97,6.9L3.24,20.62C2.73,21.13,3.09,22,3.8,22h13.16V6.9H16.97z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_3_5_bar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_3_5_bar.xml
new file mode 100644
index 0000000..8ca2eb6
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_3_5_bar.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M3.8,22H21a1,1,0,0,0,1-1V3.8a0.81 0.81 ,0,0,0-1.38-0.57L3.24,20.62A0.81 0.81 ,0,0,0,3.8,22Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.24,20.62A0.81 0.81 ,0,0,0,3.8,22H15V8.89Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml
new file mode 100644
index 0000000..fe2f04e
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,20.99V3.8c0-0.71-0.87-1.08-1.38-0.57L3.24,20.62C2.73,21.13,3.09,22,3.8,22h17.19C21.54,22,22,21.55,22,20.99z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_4_5_bar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_4_5_bar.xml
new file mode 100644
index 0000000..350b1b5
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_4_5_bar.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M3.8,22H21c0.6,0,1-0.4,1-1V3.8C22,3.4,21.6,3,21.2,3c-0.2,0-0.4,0.1-0.6,0.2L3.2,20.6c-0.3,0.3-0.3,0.8,0,1.1 C3.4,21.9,3.6,22,3.8,22z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.2,20.6C2.7,21.1,3.1,22,3.8,22H18V5.9L3.2,20.6z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_5_5_bar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_5_5_bar.xml
new file mode 100644
index 0000000..fe2f04e
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_cellular_5_5_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,20.99V3.8c0-0.71-0.87-1.08-1.38-0.57L3.24,20.62C2.73,21.13,3.09,22,3.8,22h17.19C21.54,22,22,21.55,22,20.99z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml
new file mode 100644
index 0000000..1407d0f
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open 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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@*android:drawable/ic_signal_wifi_transient_animation_drawable" >
+ <target
+ android:name="_R_G_L_7_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_0" />
+ <target
+ android:name="_R_G_L_6_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_1" />
+ <target
+ android:name="_R_G_L_6_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_2" />
+ <target
+ android:name="_R_G_L_5_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_1" />
+ <target
+ android:name="_R_G_L_5_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_2" />
+ <target
+ android:name="_R_G_L_4_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_3" />
+ <target
+ android:name="_R_G_L_4_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_4" />
+ <target
+ android:name="_R_G_L_3_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_3" />
+ <target
+ android:name="_R_G_L_3_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_4" />
+ <target
+ android:name="_R_G_L_2_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_5" />
+ <target
+ android:name="_R_G_L_2_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_6" />
+ <target
+ android:name="_R_G_L_1_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_5" />
+ <target
+ android:name="_R_G_L_1_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_6" />
+ <target
+ android:name="_R_G_L_0_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_7" />
+ <target
+ android:name="time_group"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_8" />
+</animated-vector>
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation_drawable.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation_drawable.xml
new file mode 100644
index 0000000..12092cb
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation_drawable.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_7_G"
+ android:translateX="0.10000000000000142"
+ android:translateY="3" >
+ <path
+ android:name="_R_G_L_7_G_D_0_P_0"
+ android:fillAlpha="0.3"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M23.56 5.11 C23.95,4.63 23.85,3.92 23.34,3.57 C21.57,2.36 17.45,0 11.9,0 C6.34,0 2.23,2.36 0.46,3.57 C-0.05,3.92 -0.15,4.63 0.23,5.11 C0.23,5.11 11.06,18.6 11.06,18.6 C11.48,19.13 12.29,19.13 12.72,18.6 C12.72,18.6 23.56,5.11 23.56,5.11c " />
+ </group>
+ <group
+ android:name="_R_G_L_6_G"
+ android:translateX="0.10000000000000142"
+ android:translateY="3" >
+ <path
+ android:name="_R_G_L_6_G_D_0_P_0"
+ android:fillAlpha="0.3"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M23.56 5.11 C23.95,4.63 23.85,3.92 23.34,3.57 C21.57,2.36 17.45,0 11.9,0 C6.34,0 2.23,2.36 0.46,3.57 C-0.05,3.92 -0.15,4.63 0.23,5.11 C0.23,5.11 11.06,18.6 11.06,18.6 C11.48,19.13 12.29,19.13 12.72,18.6 C12.72,18.6 23.56,5.11 23.56,5.11c " />
+ </group>
+ <group
+ android:name="_R_G_L_5_G"
+ android:translateX="5.81"
+ android:translateY="12.747" >
+ <path
+ android:name="_R_G_L_5_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M7.01 8.85 C7.01,8.85 12.12,2.5 12.12,2.5 C10.48,1.05 8.37,0.25 6.19,0.25 C3.91,0.25 1.84,1.1 0.25,2.5 C0.25,2.5 5.35,8.85 5.35,8.85 C5.78,9.38 6.58,9.38 7.01,8.85c " />
+ </group>
+ <group
+ android:name="_R_G_L_4_G"
+ android:translateX="0.10000000000000142"
+ android:translateY="3" >
+ <path
+ android:name="_R_G_L_4_G_D_0_P_0"
+ android:fillAlpha="0.3"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M23.56 5.11 C23.95,4.63 23.85,3.92 23.34,3.57 C21.57,2.36 17.45,0 11.9,0 C6.34,0 2.23,2.36 0.46,3.57 C-0.05,3.92 -0.15,4.63 0.23,5.11 C0.23,5.11 11.06,18.6 11.06,18.6 C11.48,19.13 12.29,19.13 12.72,18.6 C12.72,18.6 23.56,5.11 23.56,5.11c " />
+ </group>
+ <group
+ android:name="_R_G_L_3_G"
+ android:translateX="3.9290000000000003"
+ android:translateY="9.75" >
+ <path
+ android:name="_R_G_L_3_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M8.89 11.85 C8.89,11.85 15.88,3.15 15.88,3.15 C13.78,1.35 11.06,0.25 8.07,0.25 C5.08,0.25 2.35,1.35 0.25,3.16 C0.25,3.16 7.23,11.86 7.23,11.86 C7.66,12.38 8.46,12.38 8.89,11.85c " />
+ </group>
+ <group
+ android:name="_R_G_L_2_G"
+ android:translateX="0.10000000000000142"
+ android:translateY="3" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:fillAlpha="0.3"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M23.56 5.11 C23.95,4.63 23.85,3.92 23.34,3.57 C21.57,2.36 17.45,0 11.9,0 C6.34,0 2.23,2.36 0.46,3.57 C-0.05,3.92 -0.15,4.63 0.23,5.11 C0.23,5.11 11.06,18.6 11.06,18.6 C11.48,19.13 12.29,19.13 12.72,18.6 C12.72,18.6 23.56,5.11 23.56,5.11c " />
+ </group>
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="2.6799999999999997"
+ android:translateY="7.748" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M10.14 13.85 C10.14,13.85 18.39,3.59 18.39,3.59 C15.86,1.43 12.65,0.25 9.32,0.25 C5.86,0.25 2.69,1.51 0.25,3.6 C0.25,3.6 8.48,13.86 8.48,13.86 C8.91,14.38 9.71,14.38 10.14,13.85c " />
+ </group>
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="-0.3000000000000007"
+ android:translateY="2.75" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M12.3 0.25 C6.74,0.25 2.63,2.61 0.86,3.82 C0.35,4.17 0.25,4.88 0.63,5.36 C0.63,5.36 11.46,18.85 11.46,18.85 C11.88,19.38 12.69,19.38 13.12,18.85 C13.12,18.85 23.96,5.36 23.96,5.36 C24.35,4.88 24.25,4.17 23.74,3.82 C21.97,2.61 17.85,0.25 12.3,0.25c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_calendar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_calendar.xml
new file mode 100644
index 0000000..16359b0
--- /dev/null
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_calendar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,3H18V2a1,1,0,0,0-1-1h0a1,1,0,0,0-1,1V3H8V2A1,1,0,0,0,7,1H7A1,1,0,0,0,6,2V3H5A2,2,0,0,0,3,5V19a2,2,0,0,0,2,2H19a2,2,0,0,0,2-2V5A2,2,0,0,0,19,3Zm0,16H5V8H19Zm-3.5-6A2.5,2.5,0,1,0,18,15.5,2.5,2.5,0,0,0,15.5,13Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_corp.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_corp.xml
index 76d8882..7139313 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_corp.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_corp.xml
@@ -1,25 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorHint"
+ android:tint="?android:attr/textColorHint"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
+ <path android:pathData="M 10 4 H 14 V 6 H 10 V 4 Z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M20,6h-4V4c0-1.11-0.89-2-2-2h-4C8.89,2,8,2.89,8,4v2H4C2.89,6,2.01,6.89,2.01,8L2,19c0,1.11,0.89,2,2,2h16 c1.11,0,2-0.89,2-2V8C22,6.89,21.11,6,20,6z M14,6h-4V4h4V6z" />
+ android:pathData="M20,6h-4V4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8 C22,6.9,21.1,6,20,6z M12,15c-0.8,0-1.5-0.7-1.5-1.5S11.2,12,12,12s1.5,0.7,1.5,1.5S12.8,15,12,15z M14,6h-4V4h4V6z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_drag_handle.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_drag_handle.xml
index 3117ae1..1e14a3b 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_drag_handle.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_drag_handle.xml
@@ -1,24 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!--
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/textColorHint"
+ android:viewportHeight="24"
android:viewportWidth="24"
- android:viewportHeight="24" android:tint="?android:attr/textColorHint">
-
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M19,13H5c-0.55,0-1,0.45-1,1s0.45,1,1,1h14c0.55,0,1-0.45,1-1S19.55,13,19,13z" />
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_hourglass_top.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_hourglass_top.xml
index b389e4b..b90019c 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_hourglass_top.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_hourglass_top.xml
@@ -1,28 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!--
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary">
-
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M17,2H7C6.45,2,6,2.45,6,3l0.01,3.75c0,0.79,0.32,1.55,0.87,2.11L10,12l-3.12,3.12c-0.56,0.56-0.87,1.32-0.88,2.11L6,21
-c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1v-3.77c0-0.8-0.32-1.56-0.88-2.12L14,12l3.12-3.13C17.68,8.31,18,7.54,18,6.75V3
-C18,2.45,17.55,2,17,2z
-M15.71,16.21c0.19,0.19,0.29,0.44,0.29,0.71V20H8v-3.09c0-0.27,0.11-0.52,0.29-0.71L12,12.5L15.71,16.21z" />
+ android:pathData="M17,2H7C6.45,2,6,2.45,6,3l0.01,3.75c0,0.79,0.32,1.55,0.87,2.11L10,12l-3.12,3.12c-0.56,0.56-0.87,1.32-0.88,2.11L6,21 c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1v-3.77c0-0.8-0.32-1.56-0.88-2.12L14,12l3.12-3.13C17.68,8.31,18,7.54,18,6.75V3 C18,2.45,17.55,2,17,2z M15.71,16.21c0.19,0.19,0.29,0.44,0.29,0.71V20H8v-3.09c0-0.27,0.11-0.52,0.29-0.71L12,12.5L15.71,16.21z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_info_no_shadow.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_info_no_shadow.xml
index f50fa2b..dd095ab 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_info_no_shadow.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_info_no_shadow.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_install_no_shadow.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_install_no_shadow.xml
new file mode 100644
index 0000000..2855bfc
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_install_no_shadow.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,14c-0.55,0-1,0.45-1,1v3H6v-3c0-0.55-0.45-1-1-1s-1,0.45-1,1v3c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-3 C20,14.45,19.55,14,19,14z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.62,15.84C11.63,15.84,11.63,15.85,11.62,15.84c0.21,0.21,0.55,0.21,0.75,0l2.95-2.94c0.34-0.33,0.1-0.9-0.37-0.9H13V5 c0-0.55-0.45-1-1-1c-0.55,0-1,0.45-1,1v7H9.04c-0.47,0-0.7,0.57-0.37,0.9L11.62,15.84z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_palette.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_palette.xml
index e9a89ec..7e70942 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_palette.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_palette.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_pin.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_pin.xml
index 698f718..80232d8 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_pin.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_pin.xml
@@ -1,26 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!--
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary">
-
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M5.71,14.29C5.08,14.92,5.52,16,6.41,16H11v6c0,0.55,0.45,1,1,1s1-0.45,1-1v-6h4.59c0.89,0,1.34-1.08,0.71-1.71L16,12V5
-h0.5c0.55,0,1-0.45,1-1s-0.45-1-1-1h-9c-0.55,0-1,0.45-1,1s0.45,1,1,1H8v7L5.71,14.29z" />
+ android:pathData="M5.71,14.29C5.08,14.92,5.52,16,6.41,16H11v6c0,0.55,0.45,1,1,1s1-0.45,1-1v-6h4.59c0.89,0,1.34-1.08,0.71-1.71L16,12V5 h0.5c0.55,0,1-0.45,1-1s-0.45-1-1-1h-9c-0.55,0-1,0.45-1,1s0.45,1,1,1H8v7L5.71,14.29z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_remove_no_shadow.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
index b3288d9..f9532a1 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml
index 513633b..30e8660 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml
@@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_smartspace_preferences.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
index 4ca2967..e0b39fc4 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_split_screen.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_split_screen.xml
index 6eddf3d..c2c7ede 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_split_screen.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_split_screen.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_uninstall_no_shadow.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_uninstall_no_shadow.xml
new file mode 100644
index 0000000..b7cc52a
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_uninstall_no_shadow.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18,4h-2.5l-0.71-0.71C14.61,3.11,14.35,3,14.09,3H9.9C9.64,3,9.38,3.11,9.2,3.29L8.49,4h-2.5c-0.55,0-1,0.45-1,1 s0.45,1,1,1h12c0.55,0,1-0.45,1-1C19,4.45,18.55,4,18,4z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,19c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V7H6V19z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_warning.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_warning.xml
index 4198759..697f5d8 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_warning.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_warning.xml
@@ -1,25 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M12.87,3.49c-0.39-0.67-1.35-0.67-1.73,0l-9.27,16C1.48,20.17,1.96,21,2.73,21h18.53c0.77,0,1.25-0.83,0.87-1.5L12.87,3.49 z M11,10c0-0.55,0.45-1,1-1s1,0.45,1,1v3c0,0.55-0.45,1-1,1s-1-0.45-1-1V10z M12,18.25c-0.69,0-1.25-0.56-1.25-1.25 s0.56-1.25,1.25-1.25s1.25,0.56,1.25,1.25S12.69,18.25,12,18.25z" />
+ android:pathData="M2.73,21h18.53c0.77,0,1.25-0.83,0.87-1.5l-9.27-16c-0.39-0.67-1.35-0.67-1.73,0l-9.27,16C1.48,20.17,1.96,21,2.73,21z M11,10c0-0.55,0.45-1,1-1s1,0.45,1,1v3c0,0.55-0.45,1-1,1s-1-0.45-1-1V10z M12,15.75c0.69,0,1.25,0.56,1.25,1.25 s-0.56,1.25-1.25,1.25s-1.25-0.56-1.25-1.25S11.31,15.75,12,15.75z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_widget.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_widget.xml
index 7316c02d5..329c0d6 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_widget.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_widget.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_arrow_down_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_arrow_down_24dp.xml
new file mode 100644
index 0000000..82436f5
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_arrow_down_24dp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19.29,8.29c-0.39-0.39-1.02-0.39-1.41,0L12,14.17L6.12,8.29c-0.39-0.39-1.02-0.39-1.41,0c-0.39,0.39-0.39,1.02,0,1.41 l6.59,6.59c0.39,0.39,1.02,0.39,1.41,0l6.59-6.59C19.68,9.32,19.68,8.68,19.29,8.29z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
new file mode 100644
index 0000000..e1a8b1f
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10.42,6C10.03,5.61,9.39,5.61,9,6l0,0C8.61,6.39,8.61,7.03,9,7.42L13.59,12L9,16.58C8.61,16.97,8.61,17.61,9,18l0,0 c0.39,0.39,1.02,0.39,1.41,0l5.29-5.3c0.39-0.39,0.39-1.02,0-1.41L10.42,6z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help_actionbar.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help_actionbar.xml
new file mode 100644
index 0000000..ed6d553
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help_actionbar.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,22c5.52,0,10-4.48,10-10c0-5.52-4.48-10-10-10S2,6.48,2,12C2,17.52,6.48,22,12,22z M12,18.96 c-0.69,0-1.25-0.56-1.25-1.25c0-0.69,0.56-1.25,1.25-1.25s1.25,0.56,1.25,1.25C13.25,18.4,12.69,18.96,12,18.96z M8.16,7.92 c0.63-2.25,2.91-3.38,5.05-2.74c1.71,0.51,2.84,2.16,2.78,3.95c-0.07,2.44-2.49,2.61-2.92,5.06c-0.09,0.52-0.59,0.87-1.13,0.79 c-0.57-0.08-0.94-0.66-0.83-1.23c0.52-2.61,2.66-2.84,2.87-4.5c0.12-0.96-0.42-1.87-1.34-2.17c-1.04-0.33-2.21,0.16-2.55,1.37 C9.97,8.9,9.57,9.19,9.12,9.19C8.46,9.19,7.99,8.56,8.16,7.92z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_info_outline_24.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_info_outline_24.xml
new file mode 100644
index 0000000..3990712
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_info_outline_24.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M13,17c0,0.55-0.45,1-1,1s-1-0.45-1-1 v-5c0-0.55,0.45-1,1-1s1,0.45,1,1V17z M12,9.25c-0.69,0-1.25-0.56-1.25-1.25S11.31,6.75,12,6.75S13.25,7.31,13.25,8 S12.69,9.25,12,9.25z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_search_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_search_24dp.xml
new file mode 100644
index 0000000..30d4796
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_search_24dp.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path android:pathData="M 0.01 -0.24 H 24.01 V 23.76 H 0.01 V -0.24 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.15,10.92c0.48,2.28,2.25,4.16,4.49,4.81c2.13,0.62,4.11,0.13,5.63-0.97l4.94,4.94c0.41,0.41,1.08,0.41,1.49,0 c0.41-0.41,0.41-1.08,0-1.49l-4.94-4.94c1.1-1.53,1.59-3.5,0.97-5.63c-0.65-2.24-2.53-4-4.81-4.49C6.23,2.16,2.16,6.23,3.15,10.92z M9.5,5C11.99,5,14,7.01,14,9.5c0,2.49-2.01,4.5-4.5,4.5S5,11.99,5,9.5C5,7.01,7.01,5,9.5,5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accent.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accent.xml
new file mode 100644
index 0000000..f2741d1
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accent.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorAccent"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21.64,8.39l-1.6-2.76c-0.28-0.48-0.88-0.7-1.36-0.5l-2.14,0.91c-0.48-0.37-1.01-0.68-1.57-0.92l-0.27-2.2 C14.64,2.4,14.14,2,13.59,2h-3.18C9.86,2,9.36,2.4,9.3,2.92L9.04,5.11c-0.57,0.24-1.1,0.55-1.58,0.92L5.32,5.12 c-0.48-0.2-1.08,0.02-1.36,0.5l-1.6,2.76C2.08,8.86,2.18,9.48,2.6,9.8l1.94,1.45C4.51,11.49,4.5,11.74,4.5,12s0.01,0.51,0.04,0.76 L2.6,14.2c-0.42,0.31-0.52,0.94-0.24,1.41l1.6,2.76c0.28,0.48,0.88,0.7,1.36,0.5l2.14-0.91c0.48,0.37,1.01,0.68,1.57,0.92 l0.27,2.19C9.36,21.6,9.86,22,10.41,22h3.18c0.55,0,1.04-0.4,1.11-0.92l0.27-2.19c0.56-0.24,1.09-0.55,1.57-0.92l2.14,0.91 c0.48,0.2,1.08-0.02,1.36-0.5l1.6-2.76c0.28-0.48,0.18-1.1-0.24-1.42l-1.94-1.45c0.03-0.25,0.04-0.5,0.04-0.76 s-0.01-0.51-0.04-0.76L21.4,9.8C21.82,9.49,21.92,8.86,21.64,8.39z M12,15.5c-1.93,0-3.5-1.57-3.5-3.5s1.57-3.5,3.5-3.5 s3.5,1.57,3.5,3.5S13.93,15.5,12,15.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_backup.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_backup.xml
new file mode 100644
index 0000000..9087b96
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_backup.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M7.5,19h10c2.48,0,4.5-2.02,4.5-4.5c0-2.34-1.79-4.27-4.08-4.48C17.45,7.18,14.97,5,12,5C9.82,5,7.83,6.18,6.78,8.06 C4.09,8.41,2,10.74,2,13.5C2,16.53,4.47,19,7.5,19z M8.68,12.09l2.94-2.95c0,0,0.01-0.01,0.01-0.01c0.21-0.2,0.54-0.2,0.74,0.01 l2.95,2.95c0.34,0.33,0.1,0.9-0.37,0.9H13V16c0,0.55-0.45,1-1,1s-1-0.45-1-1v-3.01H9.05C8.58,12.99,8.35,12.42,8.68,12.09z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_storage.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_storage.xml
new file mode 100644
index 0000000..ab2186d
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_storage.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,10H5c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2C21,10.9,20.1,10,19,10z M6,13.1c-0.61,0-1.1-0.49-1.1-1.1 s0.49-1.1,1.1-1.1s1.1,0.49,1.1,1.1S6.61,13.1,6,13.1z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21,18c0-1.1-0.9-2-2-2H5c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h14C20.1,20,21,19.1,21,18z M6,19.1c-0.61,0-1.1-0.49-1.1-1.1 s0.49-1.1,1.1-1.1s1.1,0.49,1.1,1.1S6.61,19.1,6,19.1z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,4H5C3.9,4,3,4.9,3,6c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2C21,4.9,20.1,4,19,4z M6,7.1C5.39,7.1,4.9,6.61,4.9,6 S5.39,4.9,6,4.9S7.1,5.39,7.1,6S6.61,7.1,6,7.1z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_sync.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_sync.xml
new file mode 100644
index 0000000..27954a9
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_sync.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19.39,9.06c-0.19-0.48-0.74-0.72-1.22-0.53c0,0-0.01,0-0.01,0c-0.48,0.19-0.72,0.73-0.54,1.22c0,0,0,0.01,0.01,0.01 c0.28,0.71,0.43,1.46,0.43,2.23c0,3.34-2.71,6.05-6.05,6.05v-2c0-0.47-0.57-0.71-0.9-0.37l-2.94,2.95c-0.21,0.21-0.21,0.54,0,0.75 l2.94,2.95c0.33,0.33,0.9,0.1,0.9-0.37v-2c4.38,0,7.95-3.57,7.95-7.95C19.95,10.98,19.76,10,19.39,9.06z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,5.95v2c0,0.47,0.57,0.71,0.9,0.37l2.94-2.94c0.21-0.21,0.21-0.54,0-0.75L12.9,1.68C12.57,1.34,12,1.58,12,2.05v2 c-4.38,0-7.95,3.57-7.95,7.95c0,1.02,0.19,2,0.57,2.93c0.14,0.36,0.49,0.6,0.88,0.6c0.12,0,0.23-0.02,0.35-0.07c0,0,0,0,0.01,0 c0.48-0.19,0.72-0.74,0.52-1.23c-0.29-0.7-0.43-1.46-0.43-2.23C5.95,8.66,8.66,5.95,12,5.95z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_system_update.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_system_update.xml
new file mode 100644
index 0000000..149564c
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_system_update.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M17,1.01L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1.01,17,1.01z M17,19H7V5h10V19z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.62,15.84C11.63,15.84,11.63,15.85,11.62,15.84c0.21,0.21,0.55,0.21,0.75,0l2.95-2.94c0.34-0.33,0.1-0.9-0.37-0.9H13V9 c0-0.55-0.45-1-1-1c-0.55,0-1,0.45-1,1v3H9.04c-0.47,0-0.7,0.57-0.37,0.9L11.62,15.84z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_arrow_back.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_arrow_back.xml
new file mode 100644
index 0000000..b4f2a9d
--- /dev/null
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_arrow_back.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,12L20,12c0-0.56-0.45-1-1-1H7.83l4.88-4.88c0.39-0.39,0.39-1.03,0-1.42c-0.39-0.39-1.02-0.39-1.41,0l-6.59,6.59 c-0.39,0.39-0.39,1.02,0,1.41l6.59,6.59c0.39,0.39,1.02,0.39,1.41,0c0.39-0.39,0.39-1.02,0-1.41L7.83,13H19 C19.55,13,20,12.55,20,12z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast.xml
index 1477855..c13bcf9 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast.xml
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast.xml
@@ -15,10 +15,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
+ android:height="17dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="24dp" >
+ android:width="17dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M2.11,14.08C1.52,13.99,1.02,14.46,1,15.06c-0.01,0.51,0.32,0.93,0.82,1.02c2.08,0.36,3.74,2,4.1,4.08 C6.01,20.64,6.42,21,6.91,21c0.61,0,1.09-0.54,1-1.14C7.42,16.88,5.09,14.56,2.11,14.08z" />
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast_connected_fill.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast_connected_fill.xml
new file mode 100644
index 0000000..1b21db0
--- /dev/null
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast_connected_fill.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="17dp"
+ android:tint="?android:attr/colorError"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="17dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,7H5v1.63c3.96,1.28,7.09,4.41,8.37,8.37H19V7z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_headset_mic.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_headset_mic.xml
index c0bf21b..57ad6f0 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_headset_mic.xml
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_headset_mic.xml
@@ -19,7 +19,6 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="17dp" >
- <path android:pathData="M0,0h24v24H0V0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M11.4,1.02C6.62,1.33,3,5.52,3,10.31L3,17c0,1.66,1.34,3,3,3h2c0.55,0,1-0.45,1-1v-6c0-0.55-0.45-1-1-1H5l0-1.71 C5,6.45,7.96,3.11,11.79,3C15.76,2.89,19,6.06,19,10v2h-3c-0.55,0-1,0.45-1,1v6c0,0.55,0.45,1,1,1h3v1h-6c-0.55,0-1,0.45-1,1v0 c0,0.55,0.45,1,1,1h5c1.66,0,3-1.34,3-3V10C21,4.83,16.64,0.68,11.4,1.02z" />
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/stat_sys_managed_profile_status.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/stat_sys_managed_profile_status.xml
new file mode 100644
index 0000000..10d6d3d
--- /dev/null
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/stat_sys_managed_profile_status.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="17dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="17dp" >
+ <path android:pathData="M 10 4 H 14 V 6 H 10 V 4 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,6h-4V4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8 C22,6.9,21.1,6,20,6z M12,15c-0.8,0-1.5-0.7-1.5-1.5S11.2,12,12,12s1.5,0.7,1.5,1.5S12.8,15,12,15z M14,6h-4V4h4V6z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/Android.mk b/packages/overlays/IconPackFilledThemePickerOverlay/Android.mk
new file mode 100644
index 0000000..6d15603
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/Android.mk
@@ -0,0 +1,31 @@
+#
+# Copyright 2019, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := IconPackFilledThemePicker
+LOCAL_CERTIFICATE := platform
+LOCAL_PRODUCT_MODULE := true
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := IconPackFilledThemePickerOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/AndroidManifest.xml b/packages/overlays/IconPackFilledThemePickerOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..35023ab
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.theme.icon_pack.filled.themepicker"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="com.android.wallpaper" android:category="android.theme.customization.icon_pack.themepicker" android:priority="1"/>
+ <application android:label="Filled" android:hasCode="false"/>
+</manifest>
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_add_24px.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_add_24px.xml
new file mode 100644
index 0000000..1768723
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_add_24px.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M5,13h6v6c0,0.55,0.45,1,1,1s1-0.45,1-1v-6h6c0.55,0,1-0.45,1-1s-0.45-1-1-1h-6V5c0-0.55-0.45-1-1-1s-1,0.45-1,1v6H5 c-0.55,0-1,0.45-1,1S4.45,13,5,13z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_close_24px.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_close_24px.xml
new file mode 100644
index 0000000..4bfff2c
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_close_24px.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M5.7,18.3c0.39,0.39,1.02,0.39,1.41,0L12,13.41l4.89,4.89c0.39,0.39,1.02,0.39,1.41,0s0.39-1.02,0-1.41L13.41,12l4.89-4.89 c0.38-0.38,0.38-1.02,0-1.4c-0.39-0.39-1.02-0.39-1.41,0c0,0,0,0,0,0L12,10.59L7.11,5.7c-0.39-0.39-1.02-0.39-1.41,0 s-0.39,1.02,0,1.41L10.59,12L5.7,16.89C5.31,17.28,5.31,17.91,5.7,18.3z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_colorize_24px.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_colorize_24px.xml
new file mode 100644
index 0000000..aa3a925
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_colorize_24px.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.21,5.2L11.21,5.2c-0.39,0.39-0.39,1.02,0,1.41l0.71,0.71l-8.63,8.63C3.11,16.14,3,16.4,3,16.66V20c0,0.55,0.45,1,1,1 h3.34c0.27,0,0.52-0.11,0.71-0.29l8.63-8.63l0.72,0.72c0.39,0.39,1.02,0.39,1.41,0c0.39-0.39,0.39-1.02,0-1.41l-1.21-1.22L20,7.75 c0.78-0.78,0.78-2.05,0-2.83L19.08,4c-0.78-0.78-2.05-0.78-2.83,0l-2.41,2.41L12.61,5.2C12.23,4.81,11.6,4.81,11.21,5.2z M14.98,10.94L6.92,19H5v-1.92l8.06-8.06L14.98,10.94z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_delete_24px.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_delete_24px.xml
new file mode 100644
index 0000000..94c6311
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_delete_24px.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18,4h-2.5l-0.71-0.71C14.61,3.11,14.35,3,14.09,3H9.9C9.64,3,9.38,3.11,9.2,3.29L8.49,4h-2.5c-0.55,0-1,0.45-1,1 s0.45,1,1,1h12c0.55,0,1-0.45,1-1C19,4.45,18.55,4,18,4z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,19c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V7H6V19z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_font.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_font.xml
new file mode 100644
index 0000000..7603823
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_font.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12.07 8.6 L 11.94 8.6 L 10.43 13.06 L 13.56 13.06 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,2H5C3.35,2,2,3.35,2,5v14c0,1.65,1.35,3,3,3h14c1.65,0,3-1.35,3-3V5C22,3.35,20.65,2,19,2z M15.3,18l-1.01-2.87H9.7 L8.7,18H6.2l4.49-12h2.6l4.51,12H15.3z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_clock.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_clock.xml
new file mode 100644
index 0000000..11260159
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_clock.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.99,22C17.52,22,22,17.52,22,12c0-5.52-4.48-10-10.01-10C6.47,2,2,6.48,2,12C2,17.52,6.47,22,11.99,22z M11,6.82 c0-0.4,0.25-0.72,0.75-0.72s0.75,0.32,0.75,0.72v5.43l3.87,2.3c0.01,0,0.01,0.01,0.02,0.01c0.33,0.21,0.44,0.64,0.23,0.98 c-0.2,0.34-0.64,0.44-0.98,0.24L11,13V6.82z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_grid.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_grid.xml
new file mode 100644
index 0000000..0397b6c
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_grid.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,7c0.55,0,1-0.45,1-1s-0.45-1-1-1h-3V2c0-0.55-0.45-1-1-1s-1,0.45-1,1v3h-4V2c0-0.55-0.45-1-1-1s-1,0.45-1,1v3H7V2 c0-0.55-0.45-1-1-1S5,1.45,5,2v3H2C1.45,5,1,5.45,1,6s0.45,1,1,1h3v4H2c-0.55,0-1,0.45-1,1s0.45,1,1,1h3v4H2c-0.55,0-1,0.45-1,1 s0.45,1,1,1h3v3c0,0.55,0.45,1,1,1s1-0.45,1-1v-3h4v3c0,0.55,0.45,1,1,1s1-0.45,1-1v-3h4v3c0,0.55,0.45,1,1,1s1-0.45,1-1v-3h3 c0.55,0,1-0.45,1-1s-0.45-1-1-1h-3v-4h3c0.55,0,1-0.45,1-1s-0.45-1-1-1h-3V7H22z M11,17H7v-4h4V17z M11,11H7V7h4V11z M17,17h-4v-4 h4V17z M17,11h-4V7h4V11z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_theme.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_theme.xml
new file mode 100644
index 0000000..6f0462c
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_theme.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18,2H6C5.45,2,5,2.45,5,3v9c0,1.65,1.35,3,3,3h2v6c0,0.55,0.45,1,1,1h2c0.55,0,1-0.45,1-1v-6h2c1.65,0,3-1.35,3-3V3 C19,2.45,18.55,2,18,2z M17,9H7V4h2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V4h2v2c0,0.55,0.45,1,1,1c0.55,0,1-0.45,1-1V4h2V9z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_wallpaper.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_wallpaper.xml
new file mode 100644
index 0000000..ea195ca
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_nav_wallpaper.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 15.5 7 C 16.3284271247 7 17 7.67157287525 17 8.5 C 17 9.32842712475 16.3284271247 10 15.5 10 C 14.6715728753 10 14 9.32842712475 14 8.5 C 14 7.67157287525 14.6715728753 7 15.5 7 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.5,11h1C4.78,11,5,10.78,5,10.5V5h5.5C10.78,5,11,4.78,11,4.5v-1C11,3.22,10.78,3,10.5,3H5C3.9,3,3,3.9,3,5v5.5 C3,10.78,3.22,11,3.5,11z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,3h-5.5C13.22,3,13,3.22,13,3.5v1C13,4.78,13.22,5,13.5,5H19v5.5c0,0.28,0.22,0.5,0.5,0.5h1c0.28,0,0.5-0.22,0.5-0.5V5 C21,3.9,20.1,3,19,3z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.5,13h-1c-0.28,0-0.5,0.22-0.5,0.5V19h-5.5c-0.28,0-0.5,0.22-0.5,0.5v1c0,0.28,0.22,0.5,0.5,0.5H19c1.1,0,2-0.9,2-2 v-5.5C21,13.22,20.78,13,20.5,13z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10.5,19H5v-5.5C5,13.22,4.78,13,4.5,13h-1C3.22,13,3,13.22,3,13.5V19c0,1.1,0.9,2,2,2h5.5c0.28,0,0.5-0.22,0.5-0.5v-1 C11,19.22,10.78,19,10.5,19z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10.78,12.98c-0.4-0.5-1.16-0.5-1.56,0l-2.57,3.21C6.39,16.51,6.62,17,7.04,17H17c0.41,0,0.65-0.47,0.4-0.8l-1.6-2.13 c-0.4-0.53-1.2-0.53-1.6,0l-1.23,1.64L10.78,12.98z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_shapes_24px.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_shapes_24px.xml
new file mode 100644
index 0000000..cea09b56
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_shapes_24px.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,9h-3v2h3v9H10v-2H8v2c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2v-9C22,9.9,21.1,9,20,9z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M15,9c0-1.07-0.25-2.09-0.68-3C13.2,3.64,10.79,2,8,2C4.13,2,1,5.13,1,9c0,2.79,1.64,5.2,4,6.32C5.91,15.75,6.93,16,8,16 C11.87,16,15,12.87,15,9z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_tune.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_tune.xml
new file mode 100644
index 0000000..ae03b51
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_tune.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="20dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="20dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8,9c-0.55,0-1,0.45-1,1v1H4c-0.55,0-1,0.45-1,1c0,0.55,0.45,1,1,1h3v1c0,0.55,0.45,1,1,1s1-0.45,1-1v-4 C9,9.45,8.55,9,8,9z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,5h-3V4c0-0.55-0.45-1-1-1s-1,0.45-1,1v4c0,0.55,0.45,1,1,1s1-0.45,1-1V7h3c0.55,0,1-0.45,1-1C21,5.45,20.55,5,20,5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,11h-9v2h9c0.55,0,1-0.45,1-1C21,11.45,20.55,11,20,11z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,17h-7v-1c0-0.55-0.45-1-1-1s-1,0.45-1,1v4c0,0.55,0.45,1,1,1s1-0.45,1-1v-1h7c0.55,0,1-0.45,1-1S20.55,17,20,17z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M4,7h9V5H4C3.45,5,3,5.45,3,6C3,6.55,3.45,7,4,7z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3,18c0,0.55,0.45,1,1,1h5v-2H4C3.45,17,3,17.45,3,18z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_wifi_24px.xml b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_wifi_24px.xml
new file mode 100644
index 0000000..03e142e
--- /dev/null
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/res/drawable/ic_wifi_24px.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.29,19.29c0.39,0.39,1.03,0.4,1.42,0L14,18c0.47-0.47,0.38-1.28-0.22-1.58C13.25,16.15,12.64,16,12,16 c-0.64,0-1.24,0.15-1.77,0.41c-0.59,0.29-0.69,1.11-0.22,1.58L11.29,19.29z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M17.6,14.39l0.71-0.71c0.42-0.42,0.39-1.12-0.08-1.5C16.52,10.82,14.35,10,12,10c-2.34,0-4.5,0.81-6.21,2.17 c-0.47,0.37-0.51,1.07-0.09,1.49l0.71,0.71c0.35,0.36,0.92,0.39,1.32,0.08C8.91,13.54,10.39,13,12,13c1.61,0,3.1,0.55,4.29,1.47 C16.69,14.78,17.25,14.75,17.6,14.39z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21.83,10.16l0.71-0.71c0.42-0.42,0.38-1.09-0.06-1.48C19.68,5.5,16.01,4,12,4C8.01,4,4.36,5.49,1.56,7.94 C1.12,8.33,1.08,9,1.49,9.41l0.71,0.71c0.37,0.37,0.96,0.4,1.35,0.06C5.81,8.2,8.77,7,12,7c3.25,0,6.22,1.22,8.49,3.22 C20.88,10.56,21.47,10.53,21.83,10.16z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml
new file mode 100644
index 0000000..3b986a0
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@*android:drawable/ic_bluetooth_transient_animation_drawable" >
+ <target
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:animation="@*android:anim/ic_bluetooth_transient_animation_0" />
+ <target
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:animation="@*android:anim/ic_bluetooth_transient_animation_1" />
+ <target
+ android:name="time_group"
+ android:animation="@*android:anim/ic_bluetooth_transient_animation_2" />
+</animated-vector>
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bluetooth_transient_animation_drawable.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bluetooth_transient_animation_drawable.xml
new file mode 100644
index 0000000..6ea152b
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bluetooth_transient_animation_drawable.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:translateX="3.75"
+ android:translateY="1.4410000000000007" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M13.78 5.28 C13.78,5.28 9.03,0.53 9.03,0.53 C8.82,0.31 8.49,0.25 8.21,0.37 C7.93,0.48 7.75,0.75 7.75,1.06 C7.75,1.06 7.75,8.75 7.75,8.75 C7.75,8.75 3.78,4.78 3.78,4.78 C3.49,4.49 3.01,4.49 2.72,4.78 C2.43,5.07 2.43,5.55 2.72,5.84 C2.72,5.84 7.44,10.56 7.44,10.56 C7.44,10.56 2.72,15.28 2.72,15.28 C2.43,15.57 2.43,16.05 2.72,16.34 C3.01,16.63 3.49,16.63 3.78,16.34 C3.78,16.34 7.75,12.37 7.75,12.37 C7.75,12.37 7.75,20.06 7.75,20.06 C7.75,20.36 7.93,20.64 8.21,20.75 C8.31,20.79 8.4,20.81 8.5,20.81 C8.7,20.81 8.89,20.73 9.03,20.59 C9.03,20.59 13.78,15.84 13.78,15.84 C14.07,15.55 14.07,15.07 13.78,14.78 C13.78,14.78 9.56,10.56 9.56,10.56 C9.56,10.56 13.78,6.34 13.78,6.34 C14.07,6.05 14.07,5.57 13.78,5.28c M12.19 15.31 C12.19,15.31 9.25,18.25 9.25,18.25 C9.25,18.25 9.25,12.37 9.25,12.37 C9.25,12.37 12.19,15.31 12.19,15.31c M9.25 8.75 C9.25,8.75 9.25,2.87 9.25,2.87 C9.25,2.87 12.19,5.81 12.19,5.81 C12.19,5.81 9.25,8.75 9.25,8.75c " />
+ </group>
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="3.75"
+ android:translateY="1.4410000000000007" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M15.25 9.56 C14.7,9.56 14.25,10.01 14.25,10.56 C14.25,11.11 14.7,11.56 15.25,11.56 C15.8,11.56 16.25,11.11 16.25,10.56 C16.25,10.01 15.8,9.56 15.25,9.56c " />
+ </group>
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="3.75"
+ android:translateY="1.4410000000000007" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M1.25 9.56 C0.7,9.56 0.25,10.01 0.25,10.56 C0.25,11.11 0.7,11.56 1.25,11.56 C1.8,11.56 2.25,11.11 2.25,10.56 C2.25,10.01 1.8,9.56 1.25,9.56c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bt_network_pan.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bt_network_pan.xml
index cc19f94..85c2bcd 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bt_network_pan.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bt_network_pan.xml
@@ -22,7 +22,7 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M11.31,12l4.22-4.22c0.29-0.29,0.29-0.77,0-1.06l-4.75-4.75c-0.21-0.21-0.54-0.28-0.82-0.16C9.68,1.92,9.5,2.2,9.5,2.5 v7.69L5.53,6.22c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06L9.19,12l-4.72,4.72c-0.29,0.29-0.29,0.77,0,1.06s0.77,0.29,1.06,0 l3.97-3.97v7.69c0,0.3,0.18,0.58,0.46,0.69c0.09,0.04,0.19,0.06,0.29,0.06c0.2,0,0.39-0.08,0.53-0.22l4.75-4.75 c0.29-0.29,0.29-0.77,0-1.06L11.31,12z M11,4.31l2.94,2.94L11,10.19V4.31z M11,19.69v-5.88l2.94,2.94L11,19.69z" />
+ android:pathData="M11.31,12l4.22-4.22c0.29-0.29,0.29-0.77,0-1.06l-4.75-4.75c-0.21-0.21-0.54-0.28-0.82-0.16C9.68,1.92,9.5,2.2,9.5,2.5 v7.69L5.53,6.22c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06L9.19,12l-4.72,4.72c-0.29,0.29-0.29,0.77,0,1.06s0.77,0.29,1.06,0 l3.97-3.97v7.69c0,0.3,0.18,0.58,0.46,0.69c0.09,0.04,0.19,0.06,0.29,0.06c0.19,0,0.39-0.08,0.53-0.22l4.75-4.75 c0.29-0.29,0.29-0.77,0-1.06L11.31,12z M11,4.31l2.94,2.94L11,10.19V4.31z M11,19.69v-5.88l2.94,2.94L11,19.69z" />
<path
android:fillColor="@android:color/white"
android:pathData="M 16 11 C 16.5522847498 11 17 11.4477152502 17 12 C 17 12.5522847498 16.5522847498 13 16 13 C 15.4477152502 13 15 12.5522847498 15 12 C 15 11.4477152502 15.4477152502 11 16 11 Z" />
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_corp_badge.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_corp_badge.xml
new file mode 100644
index 0000000..031e5a8
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_corp_badge.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="@*android:color/accent_device_default_light"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,6h-4V4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H4C2.9,6,2,6.9,2,8v11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8 C22,6.9,21.1,6,20,6z M9.5,4c0-0.3,0.2-0.5,0.5-0.5h4c0.3,0,0.5,0.2,0.5,0.5v2h-5V4z M20.5,19c0,0.3-0.2,0.5-0.5,0.5H4 c-0.3,0-0.5-0.2-0.5-0.5V8c0-0.3,0.2-0.5,0.5-0.5h16c0.3,0,0.5,0.2,0.5,0.5V19z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 12.3 C 12.6627416998 12.3 13.2 12.8372583002 13.2 13.5 C 13.2 14.1627416998 12.6627416998 14.7 12 14.7 C 11.3372583002 14.7 10.8 14.1627416998 10.8 13.5 C 10.8 12.8372583002 11.3372583002 12.3 12 12.3 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_expand_more.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_expand_more.xml
index 858d48c..50a8742 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_expand_more.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_expand_more.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_file_copy.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_file_copy.xml
index 6a08ecb..97945f0 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_file_copy.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_file_copy.xml
@@ -23,5 +23,4 @@
<path
android:fillColor="@android:color/white"
android:pathData="M17.7,21.5H4c-0.3,0-0.5-0.2-0.5-0.5V7.3C3.5,7.1,3.4,7,3.2,7H2.3C2.1,7,2,7.1,2,7.3v14.2C2,22.3,2.7,23,3.5,23h14.2 c0.2,0,0.3-0.1,0.3-0.3v-0.9C18,21.6,17.9,21.5,17.7,21.5z M21,17V3c0-1.1-0.9-2-2-2H8C6.9,1,6,1.9,6,3v14c0,1.1,0.9,2,2,2h11 C20.1,19,21,18.1,21,17z M19,17.5H8c-0.3,0-0.5-0.2-0.5-0.5V3c0-0.3,0.2-0.5,0.5-0.5h11c0.3,0,0.5,0.2,0.5,0.5v14 C19.5,17.3,19.3,17.5,19,17.5z" />
- <path android:pathData="M0,0h24v24H0V0z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml
new file mode 100644
index 0000000..9d43e51
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@*android:drawable/ic_hotspot_transient_animation_drawable" >
+ <target
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_0" />
+ <target
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_1" />
+ <target
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_2" />
+ <target
+ android:name="time_group"
+ android:animation="@*android:anim/ic_hotspot_transient_animation_3" />
+</animated-vector>
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_hotspot_transient_animation_drawable.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_hotspot_transient_animation_drawable.xml
new file mode 100644
index 0000000..11cb9d2
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_hotspot_transient_animation_drawable.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="2"
+ android:translateY="1.552999999999999" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M8.5 10.95 C8.5,11.77 9.17,12.45 10,12.45 C10.83,12.45 11.5,11.77 11.5,10.95 C11.5,10.12 10.83,9.45 10,9.45 C9.17,9.45 8.5,10.12 8.5,10.95c " />
+ <path
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M13.01 15.01 C13.3,15.31 13.77,15.31 14.07,15.01 C15.15,13.93 15.75,12.48 15.75,10.95 C15.75,9.41 15.15,7.97 14.07,6.88 C11.82,4.64 8.18,4.64 5.94,6.88 C4.85,7.97 4.25,9.41 4.25,10.95 C4.25,12.48 4.85,13.93 5.94,15.01 C6.08,15.16 6.27,15.23 6.47,15.23 C6.66,15.23 6.85,15.16 6.99,15.01 C7.29,14.72 7.29,14.25 6.99,13.95 C6.19,13.15 5.75,12.08 5.75,10.95 C5.75,9.81 6.19,8.74 6.99,7.94 C8.65,6.28 11.35,6.28 13.01,7.94 C13.81,8.74 14.25,9.81 14.25,10.95 C14.25,12.08 13.81,13.15 13.01,13.95 C12.71,14.25 12.71,14.72 13.01,15.01c " />
+ <path
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M16.36 18.06 C16.56,18.06 16.75,17.99 16.89,17.84 C18.74,16 19.75,13.55 19.75,10.95 C19.75,8.34 18.74,5.89 16.89,4.05 C13.09,0.25 6.91,0.25 3.11,4.05 C1.26,5.89 0.25,8.34 0.25,10.95 C0.25,13.55 1.26,16 3.11,17.84 C3.4,18.13 3.87,18.13 4.17,17.84 C4.46,17.55 4.46,17.07 4.17,16.78 C2.61,15.22 1.75,13.15 1.75,10.95 C1.75,8.74 2.61,6.67 4.17,5.11 C7.38,1.9 12.62,1.9 15.83,5.11 C17.39,6.67 18.25,8.74 18.25,10.95 C18.25,13.15 17.39,15.22 15.83,16.78 C15.54,17.07 15.54,17.55 15.83,17.84 C15.98,17.99 16.17,18.06 16.36,18.06c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+</vector>
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_battery_saver.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
new file mode 100644
index 0000000..db4d302
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9.74,13.75h1.5v1.5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-1.5h1.5c0.41,0,0.75-0.34,0.75-0.75 s-0.34-0.75-0.75-0.75h-1.5v-1.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v1.5h-1.5c-0.41,0-0.75,0.34-0.75,0.75 S9.33,13.75,9.74,13.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M17,4h-3V3.49c0-0.55-0.45-1-1-1h-2c-0.55,0-1,0.45-1,1V4H7C6.45,4,6,4.45,6,5v16c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1 V5C18,4.45,17.55,4,17,4z M16.5,20.5h-9v-15h9V20.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml
new file mode 100644
index 0000000..a8e01c2
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.29,3.71L3.71,20.29C3.08,20.92,3.52,22,4.41,22H21c0.55,0,1-0.45,1-1V4.41c0-0.6-0.49-1-1.01-1 C20.75,3.41,20.5,3.5,20.29,3.71z M20.5,20.5H5.62L20.5,5.62V20.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_0_5_bar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_0_5_bar.xml
new file mode 100644
index 0000000..a8e01c2
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_0_5_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.29,3.71L3.71,20.29C3.08,20.92,3.52,22,4.41,22H21c0.55,0,1-0.45,1-1V4.41c0-0.6-0.49-1-1.01-1 C20.75,3.41,20.5,3.5,20.29,3.71z M20.5,20.5H5.62L20.5,5.62V20.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml
new file mode 100644
index 0000000..08fc66e
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.84,21.82C4,21.93,4.19,22,4.41,22h0H21c0.55,0,1-0.45,1-1V4.41c0-0.6-0.49-1-1.01-1c-0.25,0-0.5,0.09-0.7,0.29 L3.71,20.29C3.23,20.77,3.37,21.49,3.84,21.82z M20.5,5.62V20.5H11v-5.38L20.5,5.62z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_1_5_bar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_1_5_bar.xml
new file mode 100644
index 0000000..cdd770f0
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_1_5_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.5,5.62V20.5H5.62L20.5,5.62M21,3.41a1,1,0,0,0-0.7 0.3 L3.71,20.29A1,1,0,0,0,4.41,22H21a1,1,0,0,0,1-1V4.41a1,1,0,0,0-1-1Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.71,20.29A1,1,0,0,0,4.41,22H7.93V16.07Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml
new file mode 100644
index 0000000..9982d03
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.84,21.82C4,21.93,4.19,22,4.41,22h0H21c0.55,0,1-0.45,1-1V4.41c0-0.6-0.49-1-1.01-1c-0.25,0-0.5,0.09-0.7,0.29 L3.71,20.29C3.23,20.77,3.37,21.49,3.84,21.82z M20.5,5.62V20.5H13v-7.38L20.5,5.62z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_2_5_bar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_2_5_bar.xml
new file mode 100644
index 0000000..9d8c307
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_2_5_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.5,5.62V20.5H5.62L20.5,5.62M21,3.41a1,1,0,0,0-0.7 0.3 L3.71,20.29A1,1,0,0,0,4.41,22H21a1,1,0,0,0,1-1V4.41a1,1,0,0,0-1-1Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.71,20.29A1,1,0,0,0,4.41,22h7V12.55Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml
new file mode 100644
index 0000000..0e8a58a
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.84,21.82C4,21.93,4.19,22,4.41,22h0H21c0.55,0,1-0.45,1-1V4.41c0-0.6-0.49-1-1.01-1c-0.25,0-0.5,0.09-0.7,0.29 L3.71,20.29C3.23,20.77,3.37,21.49,3.84,21.82z M20.5,5.62V20.5H16V10.12L20.5,5.62z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_3_5_bar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_3_5_bar.xml
new file mode 100644
index 0000000..b1aaa3a
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_3_5_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.5,5.62V20.5H5.62L20.5,5.62M21,3.41a1,1,0,0,0-0.7 0.3 L3.71,20.29A1,1,0,0,0,4.41,22H21a1,1,0,0,0,1-1V4.41a1,1,0,0,0-1-1Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.71,20.29A1,1,0,0,0,4.41,22H15V9Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml
new file mode 100644
index 0000000..24faf35
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M4.41,22H21c0.55,0,1-0.45,1-1V4.41c0-0.89-1.08-1.34-1.71-0.71L3.71,20.29C3.08,20.92,3.52,22,4.41,22z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_4_5_bar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_4_5_bar.xml
new file mode 100644
index 0000000..3f95fa8
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_4_5_bar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.5,5.62V20.5H5.62L20.5,5.62M21,3.41a1,1,0,0,0-0.7 0.3 L3.71,20.29A1,1,0,0,0,4.41,22H21a1,1,0,0,0,1-1V4.41a1,1,0,0,0-1-1Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.71,20.29A1,1,0,0,0,4.41,22H18.48V5.52Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_5_5_bar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_5_5_bar.xml
new file mode 100644
index 0000000..24faf35
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_cellular_5_5_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M4.41,22H21c0.55,0,1-0.45,1-1V4.41c0-0.89-1.08-1.34-1.71-0.71L3.71,20.29C3.08,20.92,3.52,22,4.41,22z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml
new file mode 100644
index 0000000..5ecb826
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open 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
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@*android:drawable/ic_signal_wifi_transient_animation_drawable" >
+ <target
+ android:name="_R_G_L_4_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_0" />
+ <target
+ android:name="_R_G_L_3_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_1" />
+ <target
+ android:name="_R_G_L_3_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_2" />
+ <target
+ android:name="_R_G_L_2_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_3" />
+ <target
+ android:name="_R_G_L_2_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_4" />
+ <target
+ android:name="_R_G_L_1_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_5" />
+ <target
+ android:name="_R_G_L_1_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_6" />
+ <target
+ android:name="_R_G_L_0_G"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_7" />
+ <target
+ android:name="time_group"
+ android:animation="@*android:anim/ic_signal_wifi_transient_animation_8" />
+</animated-vector>
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation_drawable.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation_drawable.xml
new file mode 100644
index 0000000..130da57
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation_drawable.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_4_G"
+ android:translateX="0.10500000000000043"
+ android:translateY="1.7490000000000006" >
+ <path
+ android:name="_R_G_L_4_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M11.9 0.25 C7.65,0.25 3.78,1.91 0.88,4.63 C0.3,5.17 0.25,6.07 0.75,6.68 C0.75,6.68 11.12,19.31 11.12,19.31 C11.32,19.55 11.61,19.67 11.9,19.67 C12.18,19.67 12.47,19.55 12.67,19.31 C12.67,19.31 23.04,6.68 23.04,6.68 C23.54,6.07 23.49,5.17 22.91,4.63 C20.01,1.91 16.14,0.25 11.9,0.25c M11.9 17.89 C11.9,17.89 1.91,5.73 1.91,5.73 C4.64,3.16 8.18,1.75 11.9,1.75 C15.61,1.75 19.15,3.16 21.88,5.73 C21.88,5.73 11.9,17.89 11.9,17.89c " />
+ </group>
+ <group
+ android:name="_R_G_L_3_G"
+ android:translateX="0.10500000000000043"
+ android:translateY="1.75" >
+ <path
+ android:name="_R_G_L_3_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M11.9 0.25 C7.65,0.25 3.78,1.91 0.88,4.63 C0.3,5.17 0.25,6.07 0.75,6.68 C0.75,6.68 7.48,14.87 7.48,14.87 C7.48,14.87 7.48,14.87 7.48,14.87 C7.48,14.87 8,15.51 8,15.51 C8,15.51 11.12,19.31 11.12,19.31 C11.32,19.55 11.61,19.67 11.9,19.67 C12.18,19.67 12.47,19.55 12.67,19.31 C12.67,19.31 15.79,15.51 15.79,15.51 C15.79,15.51 16.31,14.87 16.31,14.87 C16.31,14.87 16.31,14.87 16.31,14.87 C16.31,14.87 23.04,6.68 23.04,6.68 C23.54,6.07 23.49,5.17 22.91,4.63 C20.01,1.91 16.14,0.25 11.9,0.25c M15.67 13.29 C15.57,13.15 15.47,13.01 15.36,12.88 C14.54,11.88 13.3,11.24 11.9,11.24 C10.5,11.24 9.25,11.88 8.43,12.88 C8.32,13.01 8.22,13.15 8.12,13.29 C8.12,13.29 1.91,5.73 1.91,5.73 C4.64,3.16 8.18,1.75 11.9,1.75 C15.61,1.75 19.15,3.16 21.88,5.73 C21.88,5.73 15.67,13.29 15.67,13.29c " />
+ </group>
+ <group
+ android:name="_R_G_L_2_G"
+ android:translateX="0.10500000000000043"
+ android:translateY="1.7490000000000006" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M11.89 0.25 C7.65,0.25 3.77,1.91 0.88,4.63 C0.3,5.17 0.25,6.07 0.75,6.68 C0.75,6.68 11.12,19.31 11.12,19.31 C11.32,19.55 11.61,19.67 11.89,19.67 C12.18,19.67 12.47,19.55 12.67,19.31 C12.67,19.31 23.04,6.68 23.04,6.68 C23.54,6.07 23.48,5.17 22.91,4.63 C20.01,1.91 16.14,0.25 11.89,0.25c M17.61 10.93 C17.5,10.8 17.4,10.66 17.28,10.54 C15.92,9.12 14.01,8.24 11.89,8.24 C9.77,8.24 7.86,9.12 6.51,10.54 C6.39,10.66 6.29,10.8 6.18,10.92 C6.18,10.92 1.91,5.73 1.91,5.73 C4.64,3.16 8.18,1.75 11.89,1.75 C15.6,1.75 19.15,3.16 21.88,5.73 C21.88,5.73 17.61,10.93 17.61,10.93c " />
+ </group>
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="0.10500000000000043"
+ android:translateY="1.7490000000000006" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M11.9 0.25 C7.65,0.25 3.78,1.91 0.88,4.63 C0.3,5.17 0.25,6.07 0.75,6.68 C0.75,6.68 3.2,9.66 3.2,9.66 C3.2,9.66 3.2,9.66 3.2,9.66 C3.2,9.66 11.12,19.31 11.12,19.31 C11.52,19.8 12.27,19.8 12.67,19.31 C12.67,19.31 20.6,9.66 20.6,9.66 C20.6,9.66 20.59,9.66 20.59,9.66 C20.59,9.66 23.04,6.68 23.04,6.68 C23.54,6.07 23.49,5.17 22.91,4.63 C20.01,1.91 16.14,0.25 11.9,0.25c M19.6 8.5 C19.51,8.41 19.43,8.32 19.34,8.23 C17.41,6.37 14.8,5.24 11.9,5.24 C8.99,5.24 6.38,6.38 4.45,8.23 C4.36,8.32 4.28,8.41 4.19,8.51 C4.19,8.51 1.91,5.73 1.91,5.73 C4.64,3.16 8.18,1.75 11.9,1.75 C15.61,1.75 19.15,3.16 21.88,5.73 C21.88,5.73 19.6,8.5 19.6,8.5c " />
+ </group>
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="0.10500000000000043"
+ android:translateY="1.75" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M11.9 0.25 C7.65,0.25 3.78,1.91 0.88,4.63 C0.3,5.17 0.25,6.07 0.75,6.68 C0.75,6.68 11.12,19.31 11.12,19.31 C11.52,19.8 12.27,19.8 12.67,19.31 C12.67,19.31 23.04,6.68 23.04,6.68 C23.54,6.07 23.49,5.17 22.91,4.63 C20.01,1.91 16.14,0.25 11.9,0.25c " />
+ </group>
+ </group>
+ <group android:name="time_group" />
+</vector>
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_calendar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_calendar.xml
new file mode 100644
index 0000000..e9dddd0
--- /dev/null
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_calendar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,3H17.5V1.75a0.75 0.75 ,0,0,0-1.5,0V3H8V1.75a0.75 0.75 ,0,0,0-1.5,0V3H5A2,2,0,0,0,3,5V19a2,2,0,0,0,2,2H19a2,2,0,0,0,2-2V5A2,2,0,0,0,19,3Zm0.5,16a0.5 0.5 ,0,0,1-0.5 0.5 H5a0.5 0.5 ,0,0,1-0.5-0.5V9h15ZM4.5,7.5V5A0.5 0.5 ,0,0,1,5,4.5H19a0.5 0.5 ,0,0,1,0.5 0.5 V7.5Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 13.5 12.5 L 16.5 12.5 Q 17.5 12.5 17.5 13.5 L 17.5 16.5 Q 17.5 17.5 16.5 17.5 L 13.5 17.5 Q 12.5 17.5 12.5 16.5 L 12.5 13.5 Q 12.5 12.5 13.5 12.5 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_corp.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_corp.xml
index dccc23c..38f515f 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_corp.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_corp.xml
@@ -1,25 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorHint"
+ android:tint="?android:attr/textColorHint"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M20,6h-4V4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H4C2.9,6,2,6.9,2,8v11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8 C22,6.9,21.1,6,20,6z M9.5,4c0-0.28,0.22-0.5,0.5-0.5h4c0.28,0,0.5,0.22,0.5,0.5v2h-5V4z M20.5,19c0,0.28-0.22,0.5-0.5,0.5H4 c-0.28,0-0.5-0.22-0.5-0.5V8c0-0.28,0.22-0.5,0.5-0.5h16c0.28,0,0.5,0.22,0.5,0.5V19z" />
+ android:pathData="M20,6h-4V4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H4C2.9,6,2,6.9,2,8v11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8 C22,6.9,21.1,6,20,6z M9.5,4c0-0.3,0.2-0.5,0.5-0.5h4c0.3,0,0.5,0.2,0.5,0.5v2h-5V4z M20.5,19c0,0.3-0.2,0.5-0.5,0.5H4 c-0.3,0-0.5-0.2-0.5-0.5V8c0-0.3,0.2-0.5,0.5-0.5h16c0.3,0,0.5,0.2,0.5,0.5V19z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 12.3 C 12.6627416998 12.3 13.2 12.8372583002 13.2 13.5 C 13.2 14.1627416998 12.6627416998 14.7 12 14.7 C 11.3372583002 14.7 10.8 14.1627416998 10.8 13.5 C 10.8 12.8372583002 11.3372583002 12.3 12 12.3 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_drag_handle.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_drag_handle.xml
index 68c0a80..1e7fcaf 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_drag_handle.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_drag_handle.xml
@@ -1,24 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!--
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/textColorHint"
+ android:viewportHeight="24"
android:viewportWidth="24"
- android:viewportHeight="24" android:tint="?android:attr/textColorHint">
-
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M5.75,10.5h12.5c0.41,0,0.75-0.34,0.75-0.75S18.66,9,18.25,9H5.75C5.34,9,5,9.34,5,9.75S5.34,10.5,5.75,10.5z" />
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_hourglass_top.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_hourglass_top.xml
index 0fd3229..28da99f 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_hourglass_top.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_hourglass_top.xml
@@ -1,29 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!--
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary">
-
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M16,3H8C7.45,3,7,3.45,7,4v1.93v0c0,0.33,0.03,0.66,0.1,0.98c0.19,0.96,0.66,1.85,1.37,2.56L11,12l-2.54,2.54
-C7.53,15.47,7,16.74,7,18.07V20c0,0.55,0.45,1,1,1h8c0.55,0,1-0.45,1-1v-1.93c0-1.33-0.53-2.6-1.46-3.54L13,12l2.54-2.54
-c0.7-0.7,1.18-1.59,1.37-2.56C16.97,6.59,17,6.26,17,5.93v0V4C17,3.45,16.55,3,16,3z
-M14.47,15.6c0.66,0.66,1.03,1.54,1.03,2.47
-v1.43h-7v-1.43c0-0.93,0.36-1.81,1.03-2.47L12,13.12L14.47,15.6z" />
+ android:pathData="M16,3H8C7.45,3,7,3.45,7,4v1.93v0c0,0.33,0.03,0.66,0.1,0.98c0.19,0.96,0.66,1.85,1.37,2.56L11,12l-2.54,2.54 C7.53,15.47,7,16.74,7,18.07V20c0,0.55,0.45,1,1,1h8c0.55,0,1-0.45,1-1v-1.93c0-1.33-0.53-2.6-1.46-3.54L13,12l2.54-2.54 c0.7-0.7,1.18-1.59,1.37-2.56C16.97,6.59,17,6.26,17,5.93v0V4C17,3.45,16.55,3,16,3z M14.47,15.6c0.66,0.66,1.03,1.54,1.03,2.47 v1.43h-7v-1.43c0-0.93,0.36-1.81,1.03-2.47L12,13.12L14.47,15.6z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_info_no_shadow.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_info_no_shadow.xml
index f799d40..168f86f 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_info_no_shadow.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_info_no_shadow.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_install_no_shadow.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_install_no_shadow.xml
new file mode 100644
index 0000000..abb597a
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_install_no_shadow.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,3c-0.41,0-0.75,0.34-0.75,0.75v9.28l-2.24-2.08c-0.3-0.28-0.78-0.26-1.06,0.04c-0.28,0.3-0.26,0.78,0.04,1.06l3.5,3.25 c0.14,0.13,0.33,0.2,0.51,0.2c0.18,0,0.37-0.07,0.51-0.2l3.49-3.25c0.3-0.28,0.32-0.76,0.04-1.06c-0.28-0.3-0.76-0.32-1.06-0.04 l-2.23,2.08V3.75C12.75,3.34,12.41,3,12,3z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M4.75,13C4.34,13,4,13.34,4,13.75v4.5C4,19.21,4.79,20,5.75,20h12.5c0.96,0,1.75-0.79,1.75-1.75v-4.5 c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v4.5c0,0.14-0.11,0.25-0.25,0.25H5.75c-0.14,0-0.25-0.11-0.25-0.25v-4.5 C5.5,13.34,5.16,13,4.75,13z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_palette.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_palette.xml
index 964955b..e086ebd 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_palette.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_palette.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<group
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_pin.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_pin.xml
index f1bf5c3..6ac4e12 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_pin.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_pin.xml
@@ -1,29 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!--
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary">
-
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M5.71,14.29C5.08,14.92,5.53,16,6.42,16h4.83v6.25c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75V16h4.84
-c0.89,0,1.34-1.08,0.71-1.71L16,12V4.5h1.23c0.41,0,0.75-0.34,0.75-0.75S17.65,3,17.23,3H16H8H6.73C6.32,3,5.98,3.34,5.98,3.75
-S6.32,4.5,6.73,4.5H8V12L5.71,14.29z
-M14.5,4.5V12c0,0.4,0.16,0.78,0.44,1.06l1.44,1.44H7.62l1.44-1.44C9.34,12.78,9.5,12.4,9.5,12
-V4.5H14.5z" />
+ android:pathData="M5.71,14.29C5.08,14.92,5.53,16,6.42,16h4.83v6.25c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75V16h4.84 c0.89,0,1.34-1.08,0.71-1.71L16,12V4.5h1.23c0.41,0,0.75-0.34,0.75-0.75S17.65,3,17.23,3H16H8H6.73C6.32,3,5.98,3.34,5.98,3.75 S6.32,4.5,6.73,4.5H8V12L5.71,14.29z M14.5,4.5V12c0,0.4,0.16,0.78,0.44,1.06l1.44,1.44H7.62l1.44-1.44C9.34,12.78,9.5,12.4,9.5,12 V4.5H14.5z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_remove_no_shadow.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
index 864a047..fcfadbe 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml
index 6ff3144..86cb525 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml
@@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_smartspace_preferences.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
index 3cc9e51..49f7327 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_split_screen.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_split_screen.xml
index aaf4900..85443eb 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_split_screen.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_split_screen.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_uninstall_no_shadow.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_uninstall_no_shadow.xml
new file mode 100644
index 0000000..75e6ce3
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_uninstall_no_shadow.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,4h-1h-4c0-0.55-0.45-1-1-1h-4C9.45,3,9,3.45,9,4H5H4C3.59,4,3.25,4.34,3.25,4.75S3.59,5.5,4,5.5h1V18 c0,1.66,1.34,3,3,3h8c1.66,0,3-1.34,3-3V5.5h1c0.41,0,0.75-0.34,0.75-0.75S20.41,4,20,4z M17.5,18c0,0.83-0.67,1.5-1.5,1.5H8 c-0.83,0-1.5-0.67-1.5-1.5V5.5h11V18z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M14.25,8c-0.41,0-0.75,0.34-0.75,0.75v7.5c0,0.41,0.34,0.75,0.75,0.75S15,16.66,15,16.25v-7.5C15,8.34,14.66,8,14.25,8z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9.75,8C9.34,8,9,8.34,9,8.75v7.5C9,16.66,9.34,17,9.75,17s0.75-0.34,0.75-0.75v-7.5C10.5,8.34,10.16,8,9.75,8z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_warning.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_warning.xml
index 63d7b78..2426f6f 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_warning.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_warning.xml
@@ -1,30 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M4.47,21h15.06c1.54,0,2.5-1.67,1.73-3L13.73,4.99c-0.39-0.67-1.06-1-1.73-1s-1.35,0.33-1.73,1L2.74,18 C1.97,19.33,2.93,21,4.47,21z M4.04,18.75l7.53-13.01c0.13-0.22,0.33-0.25,0.43-0.25s0.31,0.03,0.43,0.25l7.53,13.01 c0.13,0.22,0.05,0.41,0,0.5c-0.05,0.09-0.18,0.25-0.43,0.25H4.47c-0.25,0-0.38-0.16-0.43-0.25C3.98,19.16,3.91,18.97,4.04,18.75z" />
+ android:pathData="M12,3.99c-0.67,0-1.35,0.33-1.73,1L2.74,18c-0.77,1.33,0.19,3,1.73,3h15.06c1.54,0,2.5-1.67,1.73-3L13.73,4.99 C13.35,4.32,12.67,3.99,12,3.99z M19.96,19.25c-0.05,0.09-0.18,0.25-0.43,0.25H4.47c-0.25,0-0.38-0.16-0.43-0.25 c-0.05-0.09-0.13-0.28,0-0.5l7.53-13.01c0.13-0.22,0.33-0.25,0.43-0.25s0.31,0.03,0.43,0.25l7.53,13.01 C20.09,18.97,20.02,19.16,19.96,19.25z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M12,14.5c0.41,0,0.75-0.34,0.75-0.75v-4C12.75,9.33,12.41,9,12,9s-0.75,0.34-0.75,0.75v4C11.25,14.16,11.59,14.5,12,14.5z" />
+ android:pathData="M11.25,9.75v4c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-4C12.75,9.33,12.41,9,12,9S11.25,9.33,11.25,9.75z" />
<path
android:fillColor="@android:color/white"
android:pathData="M 12 16 C 12.5522847498 16 13 16.4477152502 13 17 C 13 17.5522847498 12.5522847498 18 12 18 C 11.4477152502 18 11 17.5522847498 11 17 C 11 16.4477152502 11.4477152502 16 12 16 Z" />
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_widget.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_widget.xml
index df3a9fd..1e84ba4 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_widget.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_widget.xml
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2019 The Android Open Source Project
+ Copyright (C) 2019 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:viewportHeight="24" android:tint="?android:attr/textColorPrimary"
+ android:tint="?android:attr/textColorPrimary"
+ android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_arrow_down_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_arrow_down_24dp.xml
new file mode 100644
index 0000000..50a8742
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_arrow_down_24dp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18.79,8.23c-0.29-0.3-0.76-0.3-1.06-0.01L12,13.82L6.27,8.21C5.98,7.92,5.5,7.93,5.21,8.23C4.92,8.52,4.93,9,5.23,9.29 l6,5.87c0.24,0.24,0.51,0.37,0.78,0.37c0.27,0,0.53-0.12,0.77-0.36l6-5.88C19.07,9,19.08,8.52,18.79,8.23z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
new file mode 100644
index 0000000..7df03ad
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8.98,18.04c0.15,0.14,0.33,0.21,0.52,0.21c0.19,0,0.39-0.08,0.54-0.23l5.12-5.24c0.49-0.49,0.49-1.07,0.01-1.55 l-5.12-5.25c-0.29-0.3-0.76-0.3-1.06-0.01c-0.3,0.29-0.3,0.76-0.01,1.06L13.82,12l-4.86,4.98C8.67,17.27,8.68,17.75,8.98,18.04z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
index 280f5df..b3f6421 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
@@ -23,5 +23,4 @@
<path
android:fillColor="@android:color/white"
android:pathData="M17.7,21.5H4c-0.3,0-0.5-0.2-0.5-0.5V7.3C3.5,7.1,3.4,7,3.2,7H2.3C2.1,7,2,7.1,2,7.3v14.2C2,22.3,2.7,23,3.5,23h14.2 c0.2,0,0.3-0.1,0.3-0.3v-0.9C18,21.6,17.9,21.5,17.7,21.5z M21,17V3c0-1.1-0.9-2-2-2H8C6.9,1,6,1.9,6,3v14c0,1.1,0.9,2,2,2h11 C20.1,19,21,18.1,21,17z M19,17.5H8c-0.3,0-0.5-0.2-0.5-0.5V3c0-0.3,0.2-0.5,0.5-0.5h11c0.3,0,0.5,0.2,0.5,0.5v14 C19.5,17.3,19.3,17.5,19,17.5z" />
- <path android:pathData="M0,0h24v24H0V0z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help_actionbar.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help_actionbar.xml
new file mode 100644
index 0000000..e0a6f95
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help_actionbar.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,22c0,0,0.01,0,0.01,0c5.5,0,9.98-4.47,9.99-9.98V12c0-5.51-4.49-10-10-10S2,6.49,2,12S6.49,22,12,22z M12,3.5 c4.69,0,8.5,3.81,8.5,8.5v0.02c0,4.68-3.81,8.48-8.49,8.48c0,0-0.01,0-0.01,0c-4.69,0-8.5-3.81-8.5-8.5S7.31,3.5,12,3.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8.67,9.98c0.4,0.1,0.81-0.15,0.9-0.56c0.11-0.47,0.33-0.86,0.65-1.19c0.94-0.94,2.59-0.94,3.54,0 c0.49,0.49,0.73,1.13,0.67,1.76c-0.06,0.57-0.36,1.06-0.84,1.38c-0.13,0.08-0.26,0.16-0.4,0.24c-0.7,0.4-1.67,0.94-1.93,2.51 c-0.07,0.41,0.21,0.8,0.61,0.86C11.92,15,11.96,15,12,15c0.36,0,0.68-0.26,0.74-0.62c0.15-0.87,0.58-1.12,1.19-1.46 c0.17-0.09,0.33-0.19,0.49-0.29c0.87-0.58,1.41-1.46,1.51-2.48c0.11-1.08-0.29-2.17-1.1-2.97c-1.51-1.51-4.15-1.51-5.66,0 c-0.52,0.51-0.88,1.17-1.05,1.9C8.02,9.48,8.27,9.88,8.67,9.98z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 16 C 12.5522847498 16 13 16.4477152502 13 17 C 13 17.5522847498 12.5522847498 18 12 18 C 11.4477152502 18 11 17.5522847498 11 17 C 11 16.4477152502 11.4477152502 16 12 16 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_info_outline_24.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_info_outline_24.xml
new file mode 100644
index 0000000..060188b
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_info_outline_24.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M4.92,4.94c-3.9,3.91-3.9,10.24,0.01,14.14s10.24,3.9,14.14-0.01C20.95,17.2,22,14.65,22,12c0-2.65-1.06-5.19-2.93-7.07 C15.16,1.03,8.83,1.03,4.92,4.94z M18,18c-1.6,1.59-3.76,2.48-6.02,2.48c-4.69-0.01-8.49-3.83-8.48-8.52 c0.01-4.69,3.83-8.49,8.52-8.48c4.69,0.01,8.49,3.83,8.48,8.52C20.49,14.25,19.6,16.41,18,18z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 7 C 12.5522847498 7 13 7.44771525017 13 8 C 13 8.55228474983 12.5522847498 9 12 9 C 11.4477152502 9 11 8.55228474983 11 8 C 11 7.44771525017 11.4477152502 7 12 7 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,10.5c-0.41,0-0.75,0.34-0.75,0.75v5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-5 C12.75,10.84,12.41,10.5,12,10.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_search_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_search_24dp.xml
new file mode 100644
index 0000000..f30a69c
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_search_24dp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19.25,20c0.19,0,0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06l-5.19-5.19C15.47,12.42,16,11.02,16,9.5 C16,5.92,13.08,3,9.5,3S3,5.92,3,9.5S5.92,16,9.5,16c1.52,0,2.92-0.53,4.03-1.41l5.19,5.19C18.87,19.93,19.06,20,19.25,20z M4.5,9.5c0-2.76,2.24-5,5-5s5,2.24,5,5s-2.24,5-5,5S4.5,12.26,4.5,9.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accent.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accent.xml
new file mode 100644
index 0000000..172c005
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accent.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorAccent"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M2.43,15.45l1.79,3.09c0.25,0.45,0.74,0.73,1.25,0.73c0.17,0,0.35-0.03,0.52-0.09l1.76-0.7c0.25,0.17,0.51,0.31,0.77,0.45 l0.26,1.84c0.09,0.71,0.69,1.24,1.42,1.24h3.61c0.72,0,1.33-0.53,1.43-1.19l0.26-1.86c0.25-0.14,0.51-0.28,0.76-0.45l1.76,0.7 c0.17,0.07,0.35,0.1,0.53,0.1c0.5,0,0.98-0.27,1.23-0.72l1.82-3.14c0.34-0.61,0.19-1.38-0.36-1.82l-1.48-1.16 c0.01-0.15,0.02-0.29,0.02-0.45s-0.01-0.3-0.02-0.45l1.48-1.16c0.55-0.43,0.7-1.19,0.35-1.84l-1.8-3.1 c-0.25-0.45-0.74-0.73-1.26-0.73c-0.17,0-0.35,0.03-0.52,0.09l-1.76,0.7c-0.25-0.17-0.51-0.31-0.77-0.45l-0.26-1.84 c-0.09-0.71-0.69-1.24-1.42-1.24h-3.61c-0.71,0-1.32,0.54-1.41,1.22L8.52,5.09C8.26,5.23,8.01,5.37,7.75,5.54L5.99,4.83 c-0.17-0.07-0.35-0.1-0.52-0.1c-0.5,0-0.98,0.27-1.22,0.72L2.43,8.55c-0.36,0.61-0.21,1.4,0.36,1.84l1.48,1.16 C4.27,11.7,4.26,11.85,4.26,12c0,0.16,0.01,0.3,0.02,0.45l-1.49,1.16C2.24,14.04,2.09,14.8,2.43,15.45z M5.2,13.63l0.63-0.49 l-0.05-0.79c-0.01-0.11-0.01-0.58,0-0.7l0.05-0.79L5.2,10.37L3.77,9.25l1.74-3l1.69,0.68l0.73,0.29l0.66-0.43 c0.19-0.13,0.4-0.25,0.65-0.38l0.67-0.36L10,5.3l0.25-1.79h3.48l0.26,1.8l0.11,0.76l0.69,0.36c0.23,0.12,0.44,0.24,0.64,0.37 l0.65,0.43l0.72-0.29l1.7-0.68l1.75,3.02l-1.43,1.12l-0.62,0.49l0.05,0.79c0.01,0.11,0.01,0.58,0,0.7l-0.05,0.79l0.62,0.49 l1.43,1.12l-1.74,3.02l-1.69-0.68l-0.72-0.29l-0.65,0.43c-0.19,0.13-0.4,0.25-0.65,0.38l-0.67,0.36l-0.11,0.75l-0.25,1.77h-3.5 L10,18.71l-0.11-0.76l-0.69-0.36c-0.23-0.12-0.44-0.24-0.64-0.37l-0.65-0.43l-0.72,0.29L5.5,17.76l-1.73-3.01L5.2,13.63z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,16c2.21,0,4-1.79,4-4s-1.79-4-4-4c-2.21,0-4,1.79-4,4S9.79,16,12,16z M12,9.5c1.38,0,2.5,1.12,2.5,2.5 s-1.12,2.5-2.5,2.5c-1.38,0-2.5-1.12-2.5-2.5S10.62,9.5,12,9.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_backup.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_backup.xml
new file mode 100644
index 0000000..4967a0e
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_backup.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M17.92,10.02C17.45,7.18,14.97,5,12,5C9.82,5,7.83,6.18,6.78,8.06C4.09,8.41,2,10.74,2,13.5C2,16.53,4.47,19,7.5,19h10 c2.48,0,4.5-2.02,4.5-4.5C22,12.16,20.21,10.23,17.92,10.02z M17.5,17.5h-10c-2.21,0-4-1.79-4-4c0-2,1.49-3.69,3.47-3.95l0.75-0.1 l0.37-0.66C8.88,7.38,10.38,6.5,12,6.5c2.18,0,4.08,1.62,4.44,3.76l0.19,1.14l1.15,0.11c1.52,0.14,2.72,1.45,2.72,2.99 C20.5,16.15,19.15,17.5,17.5,17.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12.53,9.47c-0.29-0.29-0.77-0.29-1.06,0l-2.5,2.5c-0.29,0.29-0.29,0.77,0,1.06s0.77,0.29,1.06,0l1.22-1.22v3.44 c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-3.44l1.22,1.22c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22 c0.29-0.29,0.29-0.77,0-1.06L12.53,9.47z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_data_usage.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_data_usage.xml
index e48cc14..b9c131b 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_data_usage.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_data_usage.xml
@@ -22,8 +22,8 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M12,19.52a7.5,7.5,0,0,1-0.77-15V2.06A10,10,0,1,0,22,12.77h-2.5A7.52,7.52,0,0,1,12,19.52Z" />
+ android:pathData="M12,20c-4.4,0-8-3.6-8-8c0-4.2,3.2-7.6,7.2-8V2C5.7,2.4,1.6,7.3,2,12.8c0.4,5.5,5.3,9.6,10.8,9.2c4.9-0.4,8.8-4.3,9.2-9.2 h-2C19.6,16.8,16.2,20,12,20z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M19.48,11.27H22a10,10,0,0,0-9.23-9.22v2.5A7.51,7.51,0,0,1,19.48,11.27Z" />
+ android:pathData="M20,11.2h2c-0.4-4.9-4.3-8.9-9.2-9.2v2C16.6,4.4,19.6,7.4,20,11.2z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_storage.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_storage.xml
new file mode 100644
index 0000000..0cf6f54
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_storage.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,2H3.75C3.34,2,3,2.34,3,2.75v4.5C3,7.66,3.34,8,3.75,8h16.5C20.66,8,21,7.66,21,7.25v-4.5C21,2.34,20.66,2,20.25,2 z M19.5,6.5h-15v-3h15V6.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 5.25 4.25 H 6.75 V 5.75 H 5.25 V 4.25 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,9H3.75C3.34,9,3,9.34,3,9.75v4.5C3,14.66,3.34,15,3.75,15h16.5c0.41,0,0.75-0.34,0.75-0.75v-4.5 C21,9.34,20.66,9,20.25,9z M19.5,13.5h-15v-3h15V13.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 5.25 11.25 H 6.75 V 12.75 H 5.25 V 11.25 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,16H3.75C3.34,16,3,16.34,3,16.75v4.5C3,21.66,3.34,22,3.75,22h16.5c0.41,0,0.75-0.34,0.75-0.75v-4.5 C21,16.34,20.66,16,20.25,16z M19.5,20.5h-15v-3h15V20.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 5.25 18.25 H 6.75 V 19.75 H 5.25 V 18.25 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_sync.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_sync.xml
new file mode 100644
index 0000000..5d0bab4
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_sync.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21.25,3.5c-0.41,0-0.75,0.34-0.75,0.75v2.5c-2.91-4.7-9.07-6.15-13.77-3.24C4.85,4.68,3.41,6.43,2.64,8.5 C2.55,8.91,2.81,9.3,3.21,9.39C3.54,9.46,3.88,9.3,4.03,9c1.65-4.4,6.55-6.62,10.94-4.97C16.92,4.76,18.53,6.17,19.5,8h-2.75 C16.34,8,16,8.34,16,8.75s0.34,0.75,0.75,0.75h4.5C21.66,9.5,22,9.16,22,8.75v-4.5C22,3.84,21.66,3.5,21.25,3.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21.04,14.49c-0.37-0.19-0.82-0.05-1.01,0.32C20,14.87,19.98,14.93,19.97,15c-1.65,4.4-6.55,6.62-10.94,4.97 C7.08,19.24,5.47,17.83,4.5,16h2.75C7.66,16,8,15.66,8,15.25S7.66,14.5,7.25,14.5h-4.5C2.34,14.5,2,14.84,2,15.25v4.5 c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-2.5c2.91,4.7,9.07,6.15,13.77,3.24c1.88-1.16,3.32-2.92,4.1-4.99 C21.56,15.13,21.41,14.68,21.04,14.49z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_system_update.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_system_update.xml
new file mode 100644
index 0000000..486b663
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_system_update.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8.97,13.03l2.5,2.5c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22l2.5-2.5c0.29-0.29,0.29-0.77,0-1.06 s-0.77-0.29-1.06,0l-1.22,1.22V8.75C12.75,8.34,12.41,8,12,8s-0.75,0.34-0.75,0.75v4.44l-1.22-1.22c-0.29-0.29-0.77-0.29-1.06,0 S8.68,12.74,8.97,13.03z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M16,1H8C6.34,1,5,2.34,5,4v16c0,1.66,1.34,3,3,3h8c1.66,0,3-1.34,3-3V4C19,2.34,17.66,1,16,1z M16,21.5H8 c-0.83,0-1.5-0.67-1.5-1.5h11C17.5,20.83,16.83,21.5,16,21.5z M17.5,18.5h-11v-13h11V18.5z M6.5,4c0-0.83,0.67-1.5,1.5-1.5h8 c0.83,0,1.5,0.67,1.5,1.5H6.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_arrow_back.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_arrow_back.xml
new file mode 100644
index 0000000..03f06e9
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_arrow_back.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8.2,18.79l0.03,0.03c0.01,0.01,0.02,0.02,0.04,0.04c0.31,0.28,0.78,0.26,1.06-0.05c0.28-0.31,0.26-0.78-0.05-1.06l-4.78-5 h16.59c0.46,0.04,0.86-0.29,0.91-0.75c-0.05-0.46-0.45-0.79-0.91-0.75H4.5l4.79-4.99c0.27-0.29,0.26-0.74-0.02-1.03 c-0.29-0.3-0.76-0.3-1.06-0.01l-6,6.24c-0.28,0.29-0.28,0.75,0,1.04L8.2,18.79z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast.xml
index 9386e70..fed248a 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast.xml
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast.xml
@@ -15,10 +15,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
+ android:height="17dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="24dp" >
+ android:width="17dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M2.75,14.25C2.34,14.25,2,14.59,2,15s0.34,0.75,0.75,0.75c1.93,0,3.5,1.57,3.5,3.5C6.25,19.66,6.59,20,7,20 s0.75-0.34,0.75-0.75C7.75,16.49,5.51,14.25,2.75,14.25z" />
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast_connected_fill.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast_connected_fill.xml
new file mode 100644
index 0000000..cadef69
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast_connected_fill.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="17dp"
+ android:tint="?android:attr/colorError"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="17dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M13.25,15.5c-0.41,0-0.75,0.34-0.75,0.75S12.84,17,13.25,17h5c0.41,0,0.75-0.34,0.75-0.75v-8.5C19,7.34,18.66,7,18.25,7 H5.75C5.34,7,5,7.34,5,7.75v1C5,9.16,5.34,9.5,5.75,9.5S6.5,9.16,6.5,8.75V8.5h11v7H13.25z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/stat_sys_managed_profile_status.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/stat_sys_managed_profile_status.xml
new file mode 100644
index 0000000..61206ca
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/stat_sys_managed_profile_status.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="17dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="17dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,6h-4V4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H4C2.9,6,2,6.9,2,8v11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8 C22,6.9,21.1,6,20,6z M9.5,4c0-0.3,0.2-0.5,0.5-0.5h4c0.3,0,0.5,0.2,0.5,0.5v2h-5V4z M20.5,19c0,0.3-0.2,0.5-0.5,0.5H4 c-0.3,0-0.5-0.2-0.5-0.5V8c0-0.3,0.2-0.5,0.5-0.5h16c0.3,0,0.5,0.2,0.5,0.5V19z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 12.3 C 12.6627416998 12.3 13.2 12.8372583002 13.2 13.5 C 13.2 14.1627416998 12.6627416998 14.7 12 14.7 C 11.3372583002 14.7 10.8 14.1627416998 10.8 13.5 C 10.8 12.8372583002 11.3372583002 12.3 12 12.3 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/Android.mk b/packages/overlays/IconPackRoundedThemePickerOverlay/Android.mk
new file mode 100644
index 0000000..ae48186
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/Android.mk
@@ -0,0 +1,31 @@
+#
+# Copyright 2019, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := IconPackRoundedThemePicker
+LOCAL_CERTIFICATE := platform
+LOCAL_PRODUCT_MODULE := true
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := IconPackRoundedThemePickerOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/AndroidManifest.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..9a90a05
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.theme.icon_pack.rounded.themepicker"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="com.android.wallpaper" android:category="android.theme.customization.icon_pack.themepicker" android:priority="1"/>
+ <application android:label="Rounded" android:hasCode="false"/>
+</manifest>
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_add_24px.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_add_24px.xml
new file mode 100644
index 0000000..707369a
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_add_24px.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M4.67,12.75h6.58v6.58C11.25,19.7,11.59,20,12,20s0.75-0.3,0.75-0.67v-6.58h6.58C19.7,12.75,20,12.41,20,12 s-0.3-0.75-0.67-0.75h-6.58V4.67C12.75,4.3,12.41,4,12,4s-0.75,0.3-0.75,0.67v6.58H4.67C4.3,11.25,4,11.59,4,12 S4.3,12.75,4.67,12.75z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_close_24px.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_close_24px.xml
new file mode 100644
index 0000000..1dca14d
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_close_24px.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18.78,5.22c-0.29-0.29-0.77-0.29-1.06,0L12,10.94L6.28,5.22c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06L10.94,12 l-5.72,5.72c-0.29,0.29-0.29,0.77,0,1.06C5.37,18.93,5.56,19,5.75,19s0.38-0.07,0.53-0.22L12,13.06l5.72,5.72 c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06L13.06,12l5.72-5.72 C19.07,5.99,19.07,5.51,18.78,5.22z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_colorize_24px.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_colorize_24px.xml
new file mode 100644
index 0000000..5c21b23
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_colorize_24px.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.47,4.47c-0.29,0.29-0.29,0.77,0,1.06l1.5,1.5l-9.68,9.68C3.11,16.89,3,17.15,3,17.42l0,2.58c0,0.55,0.45,1,1,1L6.58,21 c0,0,0,0,0,0c0.27,0,0.52-0.11,0.71-0.29l9.68-9.68l1.5,1.5c0.15,0.15,0.34,0.22,0.53,0.22c0.19,0,0.38-0.07,0.53-0.22 c0.29-0.29,0.29-0.77,0-1.06l-2.09-2.09l2.97-2.97c0.78-0.78,0.78-2.05,0-2.83c-0.78-0.78-2.05-0.78-2.83,0l-2.97,2.97l-2.09-2.09 C12.24,4.17,11.77,4.17,11.47,4.47z M6.38,19.5L4.5,19.49l0-1.87l9-9l1.88,1.88L6.38,19.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_delete_24px.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_delete_24px.xml
new file mode 100644
index 0000000..48a430f
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_delete_24px.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,4h-1h-4c0-0.55-0.45-1-1-1h-4C9.45,3,9,3.45,9,4H5H4C3.59,4,3.25,4.34,3.25,4.75S3.59,5.5,4,5.5h1V18 c0,1.66,1.34,3,3,3h8c1.66,0,3-1.34,3-3V5.5h1c0.41,0,0.75-0.34,0.75-0.75S20.41,4,20,4z M17.5,18c0,0.83-0.67,1.5-1.5,1.5H8 c-0.83,0-1.5-0.67-1.5-1.5V5.5h11V18z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M14.25,8c-0.41,0-0.75,0.34-0.75,0.75v7.5c0,0.41,0.34,0.75,0.75,0.75S15,16.66,15,16.25v-7.5C15,8.34,14.66,8,14.25,8z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9.75,8C9.34,8,9,8.34,9,8.75v7.5C9,16.66,9.34,17,9.75,17s0.75-0.34,0.75-0.75v-7.5C10.5,8.34,10.16,8,9.75,8z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_font.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_font.xml
new file mode 100644
index 0000000..bbae929
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_font.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,2H4C2.9,2,2,2.9,2,4v16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M20.5,20c0,0.27-0.23,0.5-0.5,0.5H4 c-0.27,0-0.5-0.23-0.5-0.5V4c0-0.27,0.23-0.5,0.5-0.5h16c0.27,0,0.5,0.23,0.5,0.5V20z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10.69,6L6.2,18h2.5l1-2.87h4.59L15.3,18h2.5L13.29,6H10.69z M10.43,13.06l1.51-4.46h0.13l1.49,4.46H10.43z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_clock.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_clock.xml
new file mode 100644
index 0000000..9c9d663
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_clock.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19.07,4.93c-3.91-3.9-10.24-3.9-14.14,0.01s-3.9,10.24,0.01,14.14s10.24,3.9,14.14-0.01C20.95,17.2,22,14.65,22,12 C22,9.35,20.94,6.81,19.07,4.93z M18,18c-1.6,1.59-3.76,2.48-6.02,2.48c-4.69-0.01-8.49-3.83-8.48-8.52 c0.01-4.69,3.83-8.49,8.52-8.48c4.69,0.01,8.49,3.83,8.48,8.52C20.49,14.25,19.6,16.41,18,18z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12.75,11.69V6.75C12.75,6.34,12.41,6,12,6s-0.75,0.34-0.75,0.75V12c0,0.2,0.08,0.39,0.22,0.53l3.25,3.25 c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06L12.75,11.69z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_grid.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_grid.xml
new file mode 100644
index 0000000..c81ca1e
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_grid.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,7C20.66,7,21,6.66,21,6.25S20.66,5.5,20.25,5.5H18.5V3.75C18.5,3.34,18.16,3,17.75,3S17,3.34,17,3.75V5.5h-4.25 V3.75C12.75,3.34,12.41,3,12,3s-0.75,0.34-0.75,0.75V5.5H7V3.75C7,3.34,6.66,3,6.25,3S5.5,3.34,5.5,3.75V5.5H3.75 C3.34,5.5,3,5.84,3,6.25S3.34,7,3.75,7H5.5v4.25H3.75C3.34,11.25,3,11.59,3,12s0.34,0.75,0.75,0.75H5.5V17H3.75 C3.34,17,3,17.34,3,17.75s0.34,0.75,0.75,0.75H5.5v1.75C5.5,20.66,5.84,21,6.25,21S7,20.66,7,20.25V18.5h4.25v1.75 c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75V18.5H17v1.75c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75V18.5h1.75 c0.41,0,0.75-0.34,0.75-0.75S20.66,17,20.25,17H18.5v-4.25h1.75c0.41,0,0.75-0.34,0.75-0.75s-0.34-0.75-0.75-0.75H18.5V7H20.25z M7,7h4.25v4.25H7V7z M7,17v-4.25h4.25V17H7z M17,17h-4.25v-4.25H17V17z M17,11.25h-4.25V7H17V11.25z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_theme.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_theme.xml
new file mode 100644
index 0000000..32d154b
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_theme.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.5,22h1c1.1,0,2-0.9,2-2v-6H16c1.66,0,3-1.34,3-3V3c0-0.55-0.45-1-1-1H6C5.45,2,5,2.45,5,3v8c0,1.66,1.34,3,3,3h1.5v6 C9.5,21.1,10.4,22,11.5,22z M9,3.5v2.75C9,6.66,9.34,7,9.75,7s0.75-0.34,0.75-0.75V3.5h3v2.75C13.5,6.66,13.84,7,14.25,7 S15,6.66,15,6.25V3.5h2.5V9h-11V3.5H9z M8,12.5c-0.83,0-1.5-0.67-1.5-1.5v-0.5h11V11c0,0.83-0.67,1.5-1.5,1.5h-3V14v6 c0,0.28-0.22,0.5-0.5,0.5h-1c-0.28,0-0.5-0.22-0.5-0.5v-6v-1.5H8z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_wallpaper.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_wallpaper.xml
new file mode 100644
index 0000000..21daf9d
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_nav_wallpaper.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 16 6.75 C 16.6903559373 6.75 17.25 7.30964406271 17.25 8 C 17.25 8.69035593729 16.6903559373 9.25 16 9.25 C 15.3096440627 9.25 14.75 8.69035593729 14.75 8 C 14.75 7.30964406271 15.3096440627 6.75 16 6.75 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.75,10.75c0.41,0,0.75-0.34,0.75-0.75V4.75c0-0.14,0.11-0.25,0.25-0.25H10c0.41,0,0.75-0.34,0.75-0.75S10.41,3,10,3 H4.75C3.79,3,3,3.79,3,4.75V10C3,10.41,3.34,10.75,3.75,10.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M10,19.5H4.75c-0.14,0-0.25-0.11-0.25-0.25V14c0-0.41-0.34-0.75-0.75-0.75S3,13.59,3,14v5.25C3,20.21,3.79,21,4.75,21H10 c0.41,0,0.75-0.34,0.75-0.75S10.41,19.5,10,19.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,13.25c-0.41,0-0.75,0.34-0.75,0.75v5.25c0,0.14-0.11,0.25-0.25,0.25H14c-0.41,0-0.75,0.34-0.75,0.75 S13.59,21,14,21h5.25c0.96,0,1.75-0.79,1.75-1.75V14C21,13.59,20.66,13.25,20.25,13.25z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19.25,3H14c-0.41,0-0.75,0.34-0.75,0.75S13.59,4.5,14,4.5h5.25c0.14,0,0.25,0.11,0.25,0.25V10 c0,0.41,0.34,0.75,0.75,0.75S21,10.41,21,10V4.75C21,3.79,20.21,3,19.25,3z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M13.73,12.37l-2.6,3.35l-1.74-2.1c-0.2-0.25-0.58-0.24-0.78,0.01l-1.99,2.56C6.36,16.52,6.59,17,7.01,17h9.98 c0.41,0,0.65-0.47,0.4-0.8l-2.87-3.83C14.32,12.11,13.93,12.11,13.73,12.37z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_shapes_24px.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_shapes_24px.xml
new file mode 100644
index 0000000..19ce4e3
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_shapes_24px.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,9h-2.51c0,0.1,0.01,0.2,0.01,0.3v1.2H20c0.28,0,0.5,0.22,0.5,0.5v9c0,0.28-0.22,0.5-0.5,0.5H10 c-0.28,0-0.5-0.22-0.5-0.5v-2.5H8V20c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2v-9C22,9.9,21.1,9,20,9z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M16,9c0-3.87-3.13-7-7-7C5.13,2,2,5.13,2,9c0,3.87,3.13,7,7,7C12.87,16,16,12.87,16,9z M3.5,9c0-3.03,2.47-5.5,5.5-5.5 s5.5,2.47,5.5,5.5s-2.47,5.5-5.5,5.5S3.5,12.03,3.5,9z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_tune.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_tune.xml
new file mode 100644
index 0000000..2a56cc5
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_tune.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="20dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="20dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.75,4.75C3.34,4.75,3,5.09,3,5.5s0.34,0.75,0.75,0.75H14v-1.5H3.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,4.75H17v-1.5c0-0.41-0.34-0.75-0.75-0.75S15.5,2.84,15.5,3.25v4.5c0,0.41,0.34,0.75,0.75,0.75S17,8.16,17,7.75v-1.5 h3.25C20.66,6.25,21,5.91,21,5.5S20.66,4.75,20.25,4.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,11.25H10v1.5h10.25c0.41,0,0.75-0.34,0.75-0.75S20.66,11.25,20.25,11.25z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3.75,17.75C3.34,17.75,3,18.09,3,18.5s0.34,0.75,0.75,0.75H10v-1.5H3.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.25,17.75H13v-1.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v4.5c0,0.41,0.34,0.75,0.75,0.75S13,21.16,13,20.75 v-1.5h7.25c0.41,0,0.75-0.34,0.75-0.75S20.66,17.75,20.25,17.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8.5,9.75C8.5,9.34,8.16,9,7.75,9S7,9.34,7,9.75v1.5H3.75C3.34,11.25,3,11.59,3,12s0.34,0.75,0.75,0.75H7v1.5 C7,14.66,7.34,15,7.75,15s0.75-0.34,0.75-0.75V9.75z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_wifi_24px.xml b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_wifi_24px.xml
new file mode 100644
index 0000000..0a1c305
--- /dev/null
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/res/drawable/ic_wifi_24px.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2.75C7.95,2.69,4.05,4.3,1.22,7.2C0.96,7.5,0.97,7.95,1.24,8.23C1.53,8.53,2,8.54,2.3,8.25c2.55-2.61,6.05-4.06,9.7-4 c3.65-0.06,7.17,1.4,9.72,4.02c0.28,0.27,0.73,0.28,1.03,0.01c0.31-0.28,0.33-0.75,0.05-1.06C19.96,4.32,16.06,2.69,12,2.75z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M15.78,14.82c0.05,0.06,0.1,0.11,0.17,0.15c0.34,0.23,0.81,0.14,1.04-0.21s0.14-0.81-0.21-1.04 c-2.64-2.64-6.91-2.64-9.55,0c-0.27,0.29-0.27,0.73,0,1.02c0.28,0.3,0.76,0.32,1.06,0.04h0.03c0,0,0,0,0.01-0.01 c2.05-2.05,5.37-2.04,7.42,0.01C15.75,14.8,15.76,14.81,15.78,14.82z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 17 C 12.8284271247 17 13.5 17.6715728753 13.5 18.5 C 13.5 19.3284271247 12.8284271247 20 12 20 C 11.1715728753 20 10.5 19.3284271247 10.5 18.5 C 10.5 17.6715728753 11.1715728753 17 12 17 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20.03,11.79c0.3-0.29,0.3-0.77,0.01-1.06h-0.01c-2.12-2.18-5.01-3.44-8.04-3.5c-3.04,0.06-5.93,1.32-8.05,3.5 c-0.29,0.3-0.28,0.77,0.01,1.06c0.3,0.29,0.77,0.28,1.06-0.01c1.85-1.88,4.36-2.96,7-3c2.62,0.05,5.11,1.13,6.95,3 C19.25,12.07,19.73,12.08,20.03,11.79z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
index 637637a..f1d2e0b 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
@@ -37,4 +37,12 @@
{@link Window#setEnsuringNavigationBarContrastWhenTransparent}. -->
<bool name="config_navBarNeedsScrim">false</bool>
+ <!-- Controls whether seamless rotation should be allowed even though the navbar can move
+ (which normally prevents seamless rotation). -->
+ <bool name="config_allowSeamlessRotationDespiteNavBarMoving">true</bool>
+
+ <!-- Controls whether the side edge gestures can always trigger the transient nav bar to
+ show. -->
+ <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
+
</resources>
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index fe92d45..5fd14a3 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -263,6 +263,14 @@
PREVIOUSLY_VISIBLE = 2;
}
+ // Types for ACTION_SHORTCUTS_CHANGED
+ enum ShortcutsChangesInfo {
+ SHORTCUTS_CHANGED_UNKNOWN = 0;
+ SHORTCUTS_CHANGED_USER_ID = 1;
+ SHORTCUTS_CHANGED_PACKAGE_COUNT = 2;
+ SHORTCUTS_CHANGED_SHORTCUT_COUNT = 3;
+ }
+
// Explanations for notification importance, derived from
// NotificationRecord.mImportanceExplanation.
enum NotificationImportanceExplanation {
@@ -4183,6 +4191,8 @@
// Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
// Tag FIELD_AUTOFILL_NUMBER_REQUESTS: number of requests made to the service (each request
// is logged by a separate AUTOFILL_REQUEST metric)
+ // NOTE: starting on OS Q, it also added the following fields:
+ // TAg FIELD_AUTOFILL_AUGMENTED_ONLY: if the session was used just for augmented autofill
AUTOFILL_SESSION_FINISHED = 919;
// meta-event: a reader has checkpointed the log here.
@@ -7213,6 +7223,82 @@
// confirmation)
DIALOG_DELETE_SIM_PROGRESS = 1714;
+ // Settings > Apps and notifications > Notifications > Gentle notifications
+ GENTLE_NOTIFICATIONS_SCREEN = 1715;
+
+ // Assistant
+ // TYPE: OPEN, CLOSE or UPDATE.
+ // For OPEN, the subtype is the innovation type for the assistant.
+ // OS: Q
+ ASSISTANT = 1716;
+
+ // ACTION: Published shortcuts in ShortcutManager changed
+ // TYPE: All the SHORTCUTS_CHANGED_* values in ShortcutsChangesInfo
+ // OS: Q
+ ACTION_SHORTCUTS_CHANGED = 1717;
+
+ // ACTION: Direct share targets loaded via ShortcutManager
+ // OS: Q
+ ACTION_DIRECT_SHARE_TARGETS_LOADED_SHORTCUT_MANAGER = 1718;
+
+ // ACTION: Direct share targets loaded via ChooserService
+ // OS: Q
+ ACTION_DIRECT_SHARE_TARGETS_LOADED_CHOOSER_SERVICE = 1719;
+
+ // Field indicating that an autofill session was created just for augmented autofill purposes.
+ // OS: Q
+ // Value: 1 for true, absent when false
+ FIELD_AUTOFILL_AUGMENTED_ONLY = 1720;
+
+ // The augmented autofill service set its whitelisted packages and activities.
+ // OS: Q
+ // Tag FIELD_AUTOFILL_SERVICE: Package of the augmented autofill service that processed the
+ // request
+ // Tag FIELD_AUTOFILL_NUMBER_PACKAGES: Number of whitelisted packages.
+ // Tag FIELD_AUTOFILL_NUMBER_ACTIVITIES: Number of whitelisted activities.
+ AUTOFILL_AUGMENTED_WHITELIST_REQUEST = 1721;
+
+ // Generic field used to indicate the number of packages in an Autofill metric (typically a
+ // whitelist request).
+ // OS: Q
+ FIELD_AUTOFILL_NUMBER_PACKAGES = 1722;
+
+ // Generic field used to indicate the number of activities in an Autofill metric (typically a
+ // whitelist request).
+ // OS: Q
+ FIELD_AUTOFILL_NUMBER_ACTIVITIES = 1723;
+
+ // Reports the result of a request made to the augmented autofill service
+ // OS: Q
+ // Type TYPE_UNKNOWN: if the type of response could not be determined
+ // Type TYPE_SUCCESS: service called onSucess() passing null
+ // Type TYPE_OPEN: service shown the UI
+ // Type TYPE_CLOSE: service hid the UI
+ // Type TYPE_ERROR: service timed out responding
+
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFILL_SERVICE: Package of the augmented autofill service that processed the
+ // request
+ // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric
+ // Tag FIELD_AUTOFILL_DURATION: how long it took (in ms) to the service to respond, or -1 if the
+ // type of response could not be determined
+ AUTOFILL_AUGMENTED_RESPONSE = 1724;
+
+ // ACTION: Settings > Initialize Search bar > Verify Slice > Invalid data
+ ACTION_VERIFY_SLICE_ERROR_INVALID_DATA = 1725;
+
+ // ACTION: Settings > Initialize Search bar > Verify Slice > Parsing error
+ ACTION_VERIFY_SLICE_PARSING_ERROR = 1726;
+
+ // ACTION: Settings > Initialize Search bar > Verify Slice > Other exception
+ ACTION_VERIFY_SLICE_OTHER_EXCEPTION = 1727;
+
+ // ---- Skipping ahead to avoid conflicts between master and release branches.
+ // OPEN: Settings > System > Gestures > Global Actions Panel
+ // CATEGORY: SETTINGS
+ // OS: Q
+ GLOBAL_ACTIONS_PANEL_SETTINGS = 1800;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 386dec4..1bd5201 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -20,8 +20,8 @@
import static android.view.autofill.AutofillManager.ACTION_START_SESSION;
import static android.view.autofill.AutofillManager.FLAG_ADD_CLIENT_ENABLED;
import static android.view.autofill.AutofillManager.FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY;
-import static android.view.autofill.AutofillManager.FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY;
import static android.view.autofill.AutofillManager.NO_SESSION;
+import static android.view.autofill.AutofillManager.RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY;
import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sVerbose;
@@ -283,7 +283,7 @@
*
* @return {@code long} whose right-most 32 bits represent the session id (which is always
* non-negative), and the left-most contains extra flags (currently either {@code 0} or
- * {@link AutofillManager#FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY}).
+ * {@link AutofillManager#RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY}).
*/
@GuardedBy("mLock")
long startSessionLocked(@NonNull IBinder activityToken, int taskId, int uid,
@@ -357,7 +357,8 @@
if (forAugmentedAutofillOnly) {
// Must embed the flag in the response, at the high-end side of the long.
// (session is always positive, so we don't have to worry about the signal bit)
- final long extraFlags = ((long) FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY) << 32;
+ final long extraFlags =
+ ((long) RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY) << 32;
final long result = extraFlags | newSession.id;
return result;
} else {
@@ -1051,6 +1052,14 @@
}
}
+ @GuardedBy("mLock")
+ void destroySessionsForAugmentedAutofillOnlyLocked() {
+ final int sessionCount = mSessions.size();
+ for (int i = sessionCount - 1; i >= 0; i--) {
+ mSessions.valueAt(i).forceRemoveSelfIfForAugmentedAutofillOnlyLocked();
+ }
+ }
+
// TODO(b/64940307): remove this method if SaveUI is refactored to be attached on activities
@GuardedBy("mLock")
void destroyFinishedSessionsLocked() {
@@ -1070,9 +1079,18 @@
@GuardedBy("mLock")
void listSessionsLocked(ArrayList<String> output) {
final int numSessions = mSessions.size();
+ if (numSessions <= 0) return;
+
+ final String fmt = "%d:%s:%s";
for (int i = 0; i < numSessions; i++) {
- output.add((mInfo != null ? mInfo.getServiceInfo().getComponentName()
- : null) + ":" + mSessions.keyAt(i));
+ final int id = mSessions.keyAt(i);
+ final String service = mInfo == null
+ ? "no_svc"
+ : mInfo.getServiceInfo().getComponentName().flattenToShortString();
+ final String augmentedService = mRemoteAugmentedAutofillServiceInfo == null
+ ? "no_aug"
+ : mRemoteAugmentedAutofillServiceInfo.getComponentName().flattenToShortString();
+ output.add(String.format(fmt, id, service, augmentedService));
}
}
@@ -1136,6 +1154,7 @@
Slog.v(TAG, "updateRemoteAugmentedAutofillService(): "
+ "destroying old remote service");
}
+ destroySessionsForAugmentedAutofillOnlyLocked();
mRemoteAugmentedAutofillService.destroy();
mRemoteAugmentedAutofillService = null;
mRemoteAugmentedAutofillServiceInfo = null;
@@ -1177,8 +1196,8 @@
* @return whether caller UID is the augmented autofill service for the user
*/
@GuardedBy("mLock")
- boolean setAugmentedAutofillWhitelistLocked(List<String> packages,
- List<ComponentName> activities, int callingUid) {
+ boolean setAugmentedAutofillWhitelistLocked(@Nullable List<String> packages,
+ @Nullable List<ComponentName> activities, int callingUid) {
if (!isCalledByAugmentedAutofillServiceLocked("setAugmentedAutofillWhitelistLocked",
callingUid)) {
@@ -1189,8 +1208,25 @@
+ activities + ")");
}
whitelistForAugmentedAutofillPackages(packages, activities);
+ final String serviceName;
+ if (mRemoteAugmentedAutofillServiceInfo != null) {
+ serviceName = mRemoteAugmentedAutofillServiceInfo.getComponentName()
+ .flattenToShortString();
+ } else {
+ Slog.e(TAG, "setAugmentedAutofillWhitelistLocked(): no service");
+ serviceName = "N/A";
+ }
- // TODO(b/122858578): log metrics
+ final LogMaker log = new LogMaker(MetricsEvent.AUTOFILL_AUGMENTED_WHITELIST_REQUEST)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, serviceName);
+ if (packages != null) {
+ log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUMBER_PACKAGES, packages.size());
+ }
+ if (activities != null) {
+ log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUMBER_ACTIVITIES, activities.size());
+ }
+ mMetricsLogger.write(log);
+
return true;
}
@@ -1233,7 +1269,6 @@
}
/**
- *
* @throws IllegalArgumentException if packages or components are empty.
*/
private void whitelistForAugmentedAutofillPackages(@Nullable List<String> packages,
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 3d392c7..80b0375 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -211,25 +211,26 @@
* Gets the {@link AutofillId} of the autofillable nodes in the {@code structure}.
*/
@NonNull
- static ArraySet<AutofillId> getAutofillableIds(@NonNull AssistStructure structure) {
- final ArraySet<AutofillId> ids = new ArraySet<>();
+ static ArrayList<AutofillId> getAutofillIds(@NonNull AssistStructure structure,
+ boolean autofillableOnly) {
+ final ArrayList<AutofillId> ids = new ArrayList<>();
final int size = structure.getWindowNodeCount();
for (int i = 0; i < size; i++) {
final WindowNode node = structure.getWindowNodeAt(i);
- addAutofillableIds(node.getRootViewNode(), ids);
+ addAutofillableIds(node.getRootViewNode(), ids, autofillableOnly);
}
return ids;
}
private static void addAutofillableIds(@NonNull ViewNode node,
- @NonNull ArraySet<AutofillId> ids) {
- if (node.getAutofillType() != View.AUTOFILL_TYPE_NONE) {
+ @NonNull ArrayList<AutofillId> ids, boolean autofillableOnly) {
+ if (!autofillableOnly || node.getAutofillType() != View.AUTOFILL_TYPE_NONE) {
ids.add(node.getAutofillId());
}
final int size = node.getChildCount();
for (int i = 0; i < size; i++) {
final ViewNode child = node.getChildAt(i);
- addAutofillableIds(child, ids);
+ addAutofillableIds(child, ids, autofillableOnly);
}
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index 609904b..d2b71e5 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -16,6 +16,8 @@
package com.android.server.autofill;
+import static android.service.autofill.augmented.Helper.logResponse;
+
import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sVerbose;
@@ -43,6 +45,7 @@
import android.view.autofill.IAutoFillManagerClient;
import com.android.internal.infra.AbstractSinglePendingRequestRemoteService;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.IResultReceiver;
final class RemoteAugmentedAutofillService
@@ -173,6 +176,7 @@
private final @Nullable AutofillValue mFocusedValue;
private final @NonNull IAutoFillManagerClient mClient;
private final @NonNull ComponentName mActivityComponent;
+ private final int mSessionId;
private final int mTaskId;
private final long mRequestTime = SystemClock.elapsedRealtime();
private final @NonNull IFillCallback mCallback;
@@ -184,6 +188,7 @@
@Nullable AutofillValue focusedValue) {
super(service, sessionId);
mClient = client;
+ mSessionId = sessionId;
mTaskId = taskId;
mActivityComponent = activityComponent;
mFocusedId = focusedId;
@@ -283,6 +288,8 @@
remoteService.dispatchOnFillTimeout(cancellation);
}
finish();
+ logResponse(MetricsEvent.TYPE_ERROR, remoteService.getComponentName().getPackageName(),
+ mActivityComponent, mSessionId, remoteService.mRequestTimeoutMs);
}
@Override
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 7b97353..66b5437 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -17,7 +17,6 @@
package com.android.server.autofill;
import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
-import static android.service.autofill.FillRequest.FLAG_AUGMENTED_AUTOFILL_REQUEST;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
import static android.view.autofill.AutofillManager.ACTION_START_SESSION;
@@ -26,7 +25,6 @@
import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
import static android.view.autofill.AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM;
import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString;
-import static android.view.autofill.Helper.toList;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static com.android.server.autofill.Helper.getNumericValue;
@@ -283,7 +281,7 @@
* on autofilling the app.
*/
@GuardedBy("mLock")
- private ArraySet<AutofillId> mAugmentedAutofillableIds;
+ private ArrayList<AutofillId> mAugmentedAutofillableIds;
/**
* When {@code true}, the session was created only to handle Augmented Autofill requests (i.e.,
@@ -336,6 +334,12 @@
return;
}
+ final ArrayList<AutofillId> ids = Helper.getAutofillIds(structure,
+ /* autofillableOnly= */false);
+ for (int i = 0; i < ids.size(); i++) {
+ ids.get(i).setSessionId(Session.this.id);
+ }
+
// Flags used to start the session.
int flags = structure.getFlags();
@@ -565,8 +569,7 @@
@GuardedBy("mLock")
private void requestNewFillResponseLocked(@NonNull ViewState viewState, int newState,
int flags) {
- if (mForAugmentedAutofillOnly || (flags & FLAG_AUGMENTED_AUTOFILL_REQUEST) != 0) {
- // TODO(b/122858578): log metrics
+ if (mForAugmentedAutofillOnly) {
if (sVerbose) {
Slog.v(TAG, "requestNewFillResponse(): triggering augmented autofill instead "
+ "(mForAugmentedAutofillOnly=" + mForAugmentedAutofillOnly
@@ -2259,6 +2262,7 @@
+ id + " destroyed");
return;
}
+ id.setSessionId(this.id);
if (sVerbose) {
Slog.v(TAG, "updateLocked(" + this.id + "): id=" + id + ", action="
+ actionAsString(action) + ", flags=" + flags);
@@ -2403,7 +2407,8 @@
return;
}
- if (mAugmentedAutofillableIds != null && mAugmentedAutofillableIds.contains(id)) {
+ if ((flags & FLAG_MANUAL_REQUEST) == 0 && mAugmentedAutofillableIds != null
+ && mAugmentedAutofillableIds.contains(id)) {
// View was already reported when server could not handle a response, but it
// triggered augmented autofill
@@ -2528,14 +2533,14 @@
}
private void notifyUnavailableToClient(int sessionFinishedState,
- @Nullable ArraySet<AutofillId> autofillableIds) {
+ @Nullable ArrayList<AutofillId> autofillableIds) {
synchronized (mLock) {
if (mCurrentViewId == null) return;
try {
if (mHasCallback) {
mClient.notifyNoFillUi(id, mCurrentViewId, sessionFinishedState);
- } else if (sessionFinishedState != 0) {
- mClient.setSessionFinished(sessionFinishedState, toList(autofillableIds));
+ } else if (sessionFinishedState != AutofillManager.STATE_UNKNOWN) {
+ mClient.setSessionFinished(sessionFinishedState, autofillableIds);
}
} catch (RemoteException e) {
Slog.e(TAG, "Error notifying client no fill UI: id=" + mCurrentViewId, e);
@@ -2661,10 +2666,10 @@
final FillContext context = getFillContextByRequestIdLocked(requestId);
- final ArraySet<AutofillId> autofillableIds;
+ final ArrayList<AutofillId> autofillableIds;
if (context != null) {
final AssistStructure structure = context.getStructure();
- autofillableIds = Helper.getAutofillableIds(structure);
+ autofillableIds = Helper.getAutofillIds(structure, /* autofillableOnly= */true);
} else {
Slog.w(TAG, "processNullResponseLocked(): no context for req " + requestId);
autofillableIds = null;
@@ -2689,6 +2694,11 @@
+ "it can be augmented. AutofillableIds: " + autofillableIds);
}
mAugmentedAutofillableIds = autofillableIds;
+ try {
+ mClient.setState(AutofillManager.SET_STATE_FLAG_FOR_AUTOFILL_ONLY);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error setting client to autofill-only", e);
+ }
}
}
@@ -2770,7 +2780,9 @@
remoteService.getComponentName().getPackageName());
mAugmentedRequestsLogs.add(log);
- remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, mCurrentViewId,
+ final AutofillId focusedId = AutofillId.withoutSession(mCurrentViewId);
+
+ remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, focusedId,
currentValue);
if (mAugmentedAutofillDestroyer == null) {
@@ -3246,6 +3258,9 @@
log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUMBER_AUGMENTED_REQUESTS,
totalAugmentedRequests);
}
+ if (mForAugmentedAutofillOnly) {
+ log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_AUGMENTED_ONLY, 1);
+ }
mMetricsLogger.write(log);
return mRemoteFillService;
@@ -3261,6 +3276,17 @@
}
@GuardedBy("mLock")
+ void forceRemoveSelfIfForAugmentedAutofillOnlyLocked() {
+ if (sVerbose) {
+ Slog.v(TAG, "forceRemoveSelfIfForAugmentedAutofillOnly(" + this.id + "): "
+ + mForAugmentedAutofillOnly);
+ }
+ if (!mForAugmentedAutofillOnly) return;
+
+ forceRemoveSelfLocked();
+ }
+
+ @GuardedBy("mLock")
void forceRemoveSelfLocked(int clientState) {
if (sVerbose) Slog.v(TAG, "forceRemoveSelfLocked(): " + mPendingSaveUi);
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 7a65a53..dbd4d8c 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -151,6 +151,7 @@
} else {
decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker, null);
}
+ decor.setClipToOutline(true);
final TextView titleView = decor.findViewById(R.id.autofill_dataset_title);
if (titleView != null) {
titleView.setText(mContext.getString(R.string.autofill_window_title, serviceLabel));
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 843aa74..73f5cb8 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -297,6 +297,9 @@
// First apply the unconditional transformations (if any) to the templates.
final ArrayList<Pair<Integer, InternalTransformation>> transformations =
customDescription.getTransformations();
+ if (sVerbose) {
+ Slog.v(TAG, "applyCustomDescription(): transformations = " + transformations);
+ }
if (transformations != null) {
if (!InternalTransformation.batchApply(valueFinder, template, transformations)) {
Slog.w(TAG, "could not apply main transformations on custom description");
@@ -345,6 +348,10 @@
// Apply batch updates (if any).
final ArrayList<Pair<InternalValidator, BatchUpdates>> updates =
customDescription.getUpdates();
+ if (sVerbose) {
+ Slog.v(TAG, "applyCustomDescription(): view = " + customSubtitleView
+ + " updates=" + updates);
+ }
if (updates != null) {
final int size = updates.size();
if (sDebug) Slog.d(TAG, "custom description has " + size + " batch updates");
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 79afe8e..302e3ff 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -49,6 +49,7 @@
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.DumpUtils;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
@@ -71,6 +72,9 @@
public static final boolean MORE_DEBUG = false;
public static final boolean DEBUG_SCHEDULING = true;
+ @VisibleForTesting
+ static final String DUMP_RUNNING_USERS_MESSAGE = "Backup Manager is running for users:";
+
// The published binder is a singleton Trampoline object that calls through to the proper code.
// This indirection lets us turn down the heavy implementation object on the fly without
// disturbing binders that have been cached elsewhere in the system.
@@ -849,6 +853,23 @@
/** Prints service state for 'dumpsys backup'. */
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) {
+ return;
+ }
+
+ if (args != null) {
+ for (String arg : args) {
+ if ("users".equals(arg.toLowerCase())) {
+ pw.print(DUMP_RUNNING_USERS_MESSAGE);
+ for (int i = 0; i < mServiceUsers.size(); i++) {
+ pw.print(" " + mServiceUsers.keyAt(i));
+ }
+ pw.println();
+ return;
+ }
+ }
+ }
+
UserBackupManagerService userBackupManagerService =
getServiceForUserIfCallerHasPermission(UserHandle.USER_SYSTEM, "dump()");
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 32a8144..c0af99c 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -101,7 +101,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.IBackupTransport;
-import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.AppWidgetBackupBridge;
import com.android.server.EventLogTags;
@@ -3470,8 +3469,6 @@
/** Prints service state for 'dumpsys backup'. */
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
-
long identityToken = Binder.clearCallingIdentity();
try {
if (args != null) {
@@ -3480,6 +3477,8 @@
pw.println("'dumpsys backup' optional arguments:");
pw.println(" -h : this help text");
pw.println(" a[gents] : dump information about defined backup agents");
+ pw.println(" users : dump the list of users for which backup service "
+ + "is running");
return;
} else if ("agents".startsWith(arg)) {
dumpAgents(pw);
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 4399e42..67c3d01 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -54,6 +54,7 @@
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.view.contentcapture.ContentCaptureCondition;
import android.view.contentcapture.DataRemovalRequest;
@@ -552,6 +553,39 @@
+ " for user " + mUserId);
}
mMaster.mGlobalContentCaptureOptions.setWhitelist(mUserId, packages, activities);
+
+ // Must disable session that are not the whitelist anymore...
+ final int numSessions = mSessions.size();
+ if (numSessions <= 0) return;
+
+ // ...but without holding the lock on mGlobalContentCaptureOptions
+ final SparseBooleanArray blacklistedSessions = new SparseBooleanArray(numSessions);
+
+ for (int i = 0; i < numSessions; i++) {
+ final ContentCaptureServerSession session = mSessions.valueAt(i);
+ final boolean whitelisted = mMaster.mGlobalContentCaptureOptions
+ .isWhitelisted(mUserId, session.appComponentName);
+ if (!whitelisted) {
+ final int sessionId = mSessions.keyAt(i);
+ if (mMaster.debug) {
+ Slog.d(TAG, "marking session " + sessionId + " (" + session.appComponentName
+ + ") for un-whitelisting");
+ }
+ blacklistedSessions.append(sessionId, true);
+ }
+ }
+ final int numBlacklisted = blacklistedSessions.size();
+
+ if (numBlacklisted <= 0) return;
+
+ synchronized (mLock) {
+ for (int i = 0; i < numBlacklisted; i++) {
+ final int sessionId = blacklistedSessions.keyAt(i);
+ if (mMaster.debug) Slog.d(TAG, "un-whitelisting " + sessionId);
+ final ContentCaptureServerSession session = mSessions.get(sessionId);
+ session.setContentCaptureEnabledLocked(false);
+ }
+ }
}
@Override
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index 2643db1..aa63e40 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -72,6 +72,8 @@
private final Object mLock;
+ public final ComponentName appComponentName;
+
ContentCaptureServerSession(@NonNull Object lock, @NonNull IBinder activityToken,
@NonNull ContentCapturePerUserService service, @NonNull ComponentName appComponentName,
@NonNull IResultReceiver sessionStateReceiver, int taskId, int displayId, int sessionId,
@@ -79,6 +81,7 @@
Preconditions.checkArgument(sessionId != NO_SESSION_ID);
mLock = lock;
mActivityToken = activityToken;
+ this.appComponentName = appComponentName;
mService = service;
mId = sessionId;
mUid = uid;
@@ -228,6 +231,7 @@
pw.print(prefix); pw.print("uid: "); pw.print(mUid); pw.println();
pw.print(prefix); pw.print("context: "); mContentCaptureContext.dump(pw); pw.println();
pw.print(prefix); pw.print("activity token: "); pw.println(mActivityToken);
+ pw.print(prefix); pw.print("app component: "); pw.println(appComponentName);
pw.print(prefix); pw.print("has autofill callback: ");
}
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
index 9b70272..7709311 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
@@ -28,6 +28,7 @@
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
+import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
import android.os.Bundle;
import android.os.RemoteException;
@@ -99,11 +100,17 @@
ActivityManager.TaskSnapshot snapshot =
mActivityTaskManagerInternal.getTaskSnapshot(taskId, false);
GraphicBuffer snapshotBuffer = null;
+ int colorSpaceId = 0;
if (snapshot != null) {
snapshotBuffer = snapshot.getSnapshot();
+ ColorSpace colorSpace = snapshot.getColorSpace();
+ if (colorSpace != null) {
+ colorSpaceId = colorSpace.getId();
+ }
}
- service.provideContextImage(taskId, snapshotBuffer, imageContextRequestExtras);
+ service.provideContextImage(taskId, snapshotBuffer, colorSpaceId,
+ imageContextRequestExtras);
}
}
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java
index 4b36352..a8b7b81 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java
@@ -68,9 +68,9 @@
}
void provideContextImage(int taskId, @Nullable GraphicBuffer contextImage,
- @NonNull Bundle imageContextRequestExtras) {
+ int colorSpaceId, @NonNull Bundle imageContextRequestExtras) {
scheduleAsyncRequest((s) -> s.provideContextImage(taskId, contextImage,
- imageContextRequestExtras));
+ colorSpaceId, imageContextRequestExtras));
}
void suggestContentSelections(
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 1220e82..72899f6 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -78,6 +78,7 @@
import android.util.KeyValueListParser;
import android.util.Log;
import android.util.LongArrayQueue;
+import android.util.MutableBoolean;
import android.util.NtpTrustedTime;
import android.util.Pair;
import android.util.Slog;
@@ -1764,8 +1765,7 @@
+ ", callingPackage: " + callingPackage;
// STOPSHIP (b/128866264): Just to catch breakages. Remove before final release.
Slog.wtf(TAG, errorMsg);
- // TODO b/129995049: Resume throwing after some soak time without errors
- // throw new UnsupportedOperationException(errorMsg);
+ throw new UnsupportedOperationException(errorMsg);
}
setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
interval, operation, directReceiver, listenerTag, flags, true, workSource,
@@ -3188,6 +3188,16 @@
mPendingBackgroundAlarms.removeAt(i);
}
}
+ // If we're currently keying off of this app's alarms for doze transitions,
+ // make sure to reset to other triggers.
+ if (mNextWakeFromIdle != null && mNextWakeFromIdle.uid == uid) {
+ mNextWakeFromIdle = null;
+ }
+ if (mPendingIdleUntil != null && mPendingIdleUntil.uid == uid) {
+ // Should never happen - only the system uid is allowed to set idle-until alarms
+ Slog.wtf(TAG, "Removed app uid " + uid + " set idle-until alarm!");
+ mPendingIdleUntil = null;
+ }
if (didRemove) {
if (DEBUG_BATCH) {
Slog.v(TAG, "remove(uid) changed bounds; rebatching");
@@ -3208,7 +3218,14 @@
}
boolean didRemove = false;
- final Predicate<Alarm> whichAlarms = (Alarm a) -> a.matches(packageName);
+ final MutableBoolean removedNextWakeFromIdle = new MutableBoolean(false);
+ final Predicate<Alarm> whichAlarms = (Alarm a) -> {
+ final boolean didMatch = a.matches(packageName);
+ if (didMatch && a == mNextWakeFromIdle) {
+ removedNextWakeFromIdle.value = true;
+ }
+ return didMatch;
+ };
final boolean oldHasTick = haveBatchesTimeTickAlarm(mAlarmBatches);
for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
Batch b = mAlarmBatches.get(i);
@@ -3243,6 +3260,11 @@
mPendingBackgroundAlarms.removeAt(i);
}
}
+ // If we're currently keying off of this app's alarms for doze transitions,
+ // make sure to reset to other triggers.
+ if (removedNextWakeFromIdle.value) {
+ mNextWakeFromIdle = null;
+ }
if (didRemove) {
if (DEBUG_BATCH) {
Slog.v(TAG, "remove(package) changed bounds; rebatching");
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 6573c3b..188d654 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1136,11 +1136,21 @@
public void unbindBluetoothProfileService(int bluetoothProfile,
IBluetoothProfileServiceConnection proxy) {
synchronized (mProfileServices) {
- ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
+ Integer profile = new Integer(bluetoothProfile);
+ ProfileServiceConnections psc = mProfileServices.get(profile);
if (psc == null) {
return;
}
psc.removeProxy(proxy);
+ if (psc.isEmpty()) {
+ // All prxoies are disconnected, unbind with the service.
+ try {
+ mContext.unbindService(psc);
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
+ }
+ mProfileServices.remove(profile);
+ }
}
}
@@ -1298,6 +1308,10 @@
mProxies.kill();
}
+ private boolean isEmpty() {
+ return mProxies.getRegisteredCallbackCount() == 0;
+ }
+
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// remove timeout message
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 55f9826..facc299 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -40,7 +40,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.uidRulesToString;
-import static android.net.shared.NetworkMonitorUtils.isValidationRequired;
+import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired;
import static android.os.Process.INVALID_UID;
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IPPROTO_UDP;
@@ -2826,8 +2826,8 @@
}
}
- private boolean networkRequiresValidation(NetworkAgentInfo nai) {
- return isValidationRequired(nai.networkCapabilities);
+ private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) {
+ return isPrivateDnsValidationRequired(nai.networkCapabilities);
}
private void handleFreshlyValidatedNetwork(NetworkAgentInfo nai) {
@@ -2845,7 +2845,7 @@
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
handlePerNetworkPrivateDnsConfig(nai, cfg);
- if (networkRequiresValidation(nai)) {
+ if (networkRequiresPrivateDnsValidation(nai)) {
handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
}
}
@@ -2854,7 +2854,7 @@
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;
+ if (!networkRequiresPrivateDnsValidation(nai)) return;
// Notify the NetworkAgentInfo/NetworkMonitor in case NetworkMonitor needs to cancel or
// schedule DNS resolutions. If a DNS resolution is required the
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 2055b64..fe22dcd 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -30,6 +30,7 @@
import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.net.IIpSecService;
import android.net.INetd;
import android.net.IpSecAlgorithm;
@@ -1276,7 +1277,7 @@
public synchronized IpSecTunnelInterfaceResponse createTunnelInterface(
String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder,
String callingPackage) {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
checkNotNull(binder, "Null Binder passed to createTunnelInterface");
checkNotNull(underlyingNetwork, "No underlying network was specified");
checkInetAddress(localAddr);
@@ -1362,7 +1363,7 @@
@Override
public synchronized void addAddressToTunnelInterface(
int tunnelResourceId, LinkAddress localAddr, String callingPackage) {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
// Get tunnelInterface record; if no such interface is found, will throw
@@ -1391,7 +1392,7 @@
@Override
public synchronized void removeAddressFromTunnelInterface(
int tunnelResourceId, LinkAddress localAddr, String callingPackage) {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
// Get tunnelInterface record; if no such interface is found, will throw
@@ -1420,7 +1421,7 @@
@Override
public synchronized void deleteTunnelInterface(
int resourceId, String callingPackage) throws RemoteException {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
releaseResource(userRecord.mTunnelInterfaceRecords, resourceId);
}
@@ -1549,7 +1550,12 @@
private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS;
- private void enforceTunnelPermissions(String callingPackage) {
+ private void enforceTunnelFeatureAndPermissions(String callingPackage) {
+ if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) {
+ throw new UnsupportedOperationException(
+ "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS");
+ }
+
checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels");
switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
case AppOpsManager.MODE_DEFAULT:
@@ -1621,7 +1627,7 @@
IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException {
checkNotNull(c);
if (c.getMode() == IpSecTransform.MODE_TUNNEL) {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
}
checkIpSecConfig(c);
checkNotNull(binder, "Null Binder passed to createTransform");
@@ -1729,7 +1735,7 @@
public synchronized void applyTunnelModeTransform(
int tunnelResourceId, int direction,
int transformResourceId, String callingPackage) throws RemoteException {
- enforceTunnelPermissions(callingPackage);
+ enforceTunnelFeatureAndPermissions(callingPackage);
checkDirection(direction);
int callingUid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 44fc45e..d52fe81 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -120,7 +120,9 @@
import com.android.server.location.PassiveProvider;
import com.android.server.location.RemoteListenerHelper;
+import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
+import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -2299,6 +2301,7 @@
private boolean mIsForegroundUid;
private Location mLastFixBroadcast;
private long mLastStatusBroadcast;
+ private Throwable mStackTrace; // for debugging only
/**
* Note: must be constructed with lock held.
@@ -2311,6 +2314,10 @@
mIsForegroundUid = isImportanceForeground(
mActivityManager.getPackageImportance(mReceiver.mCallerIdentity.mPackageName));
+ if (D && receiver.mCallerIdentity.mPid == Process.myPid()) {
+ mStackTrace = new Throwable();
+ }
+
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records == null) {
records = new ArrayList<>();
@@ -2361,11 +2368,26 @@
@Override
public String toString() {
- return "UpdateRecord[" + mProvider + " " + mReceiver.mCallerIdentity.mPackageName
- + "(" + mReceiver.mCallerIdentity.mUid + (mIsForegroundUid ? " foreground"
- : " background")
- + ")" + " " + mRealRequest + " "
- + mReceiver.mWorkSource + "]";
+ StringBuilder b = new StringBuilder("UpdateRecord[");
+ b.append(mProvider).append(" ");
+ b.append(mReceiver.mCallerIdentity.mPackageName);
+ b.append("(").append(mReceiver.mCallerIdentity.mUid);
+ if (mIsForegroundUid) {
+ b.append(" foreground");
+ } else {
+ b.append(" background");
+ }
+ b.append(") ");
+ b.append(mRealRequest).append(" ").append(mReceiver.mWorkSource);
+
+ if (mStackTrace != null) {
+ ByteArrayOutputStream tmp = new ByteArrayOutputStream();
+ mStackTrace.printStackTrace(new PrintStream(tmp));
+ b.append("\n\n").append(tmp.toString()).append("\n");
+ }
+
+ b.append("]");
+ return b.toString();
}
}
@@ -3642,6 +3664,13 @@
}
}
+ if (!mIgnoreSettingsPackageWhitelist.isEmpty()) {
+ pw.println(" Bypass Whitelisted Packages:");
+ for (String packageName : mIgnoreSettingsPackageWhitelist) {
+ pw.println(" " + packageName);
+ }
+ }
+
if (mLocationFudger != null) {
pw.append(" fudger: ");
mLocationFudger.dump(fd, pw, args);
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 7b5b419..3267114 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -529,8 +529,7 @@
while (pit.hasNext()) {
MonitoredPackage monitoredPackage = pit.next();
String packageName = monitoredPackage.getName();
- if (monitoredPackage.getHealthCheckStateLocked()
- != MonitoredPackage.STATE_PASSED) {
+ if (monitoredPackage.isPendingHealthChecksLocked()) {
packages.add(packageName);
}
}
@@ -685,13 +684,13 @@
}
}
- /** Adds a {@link DeviceConfig#OnPropertyChangedListener}. */
+ /** Adds a {@link DeviceConfig#OnPropertiesChangedListener}. */
private void setPropertyChangedListenerLocked() {
- DeviceConfig.addOnPropertyChangedListener(
+ DeviceConfig.addOnPropertiesChangedListener(
DeviceConfig.NAMESPACE_ROLLBACK,
mContext.getMainExecutor(),
- (namespace, name, value) -> {
- if (!DeviceConfig.NAMESPACE_ROLLBACK.equals(namespace)) {
+ (properties) -> {
+ if (!DeviceConfig.NAMESPACE_ROLLBACK.equals(properties.getNamespace())) {
return;
}
updateConfigs();
@@ -1093,7 +1092,10 @@
*/
@GuardedBy("mLock")
public long getShortestScheduleDurationMsLocked() {
- return Math.min(toPositive(mDurationMs), toPositive(mHealthCheckDurationMs));
+ // Consider health check duration only if #isPendingHealthChecksLocked is true
+ return Math.min(toPositive(mDurationMs),
+ isPendingHealthChecksLocked()
+ ? toPositive(mHealthCheckDurationMs) : Long.MAX_VALUE);
}
/**
@@ -1106,6 +1108,15 @@
}
/**
+ * Returns {@code true} if the package, {@link #getName} is expecting health check results
+ * {@code false} otherwise.
+ */
+ @GuardedBy("mLock")
+ public boolean isPendingHealthChecksLocked() {
+ return mHealthCheckState == STATE_ACTIVE || mHealthCheckState == STATE_INACTIVE;
+ }
+
+ /**
* Updates the health check state based on {@link #mHasPassedHealthCheck}
* and {@link #mHealthCheckDurationMs}.
*
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index baec3cc..fc355b7 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -49,7 +49,6 @@
import android.Manifest;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.KeyguardManager;
@@ -60,7 +59,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.PackageManager;
@@ -98,7 +96,6 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
-import android.os.UserManagerInternal;
import android.os.storage.DiskInfo;
import android.os.storage.IObbActionListener;
import android.os.storage.IStorageEventListener;
@@ -117,13 +114,11 @@
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.DataUnit;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.Xml;
@@ -179,8 +174,6 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
@@ -293,6 +286,7 @@
private static final String ATTR_NICKNAME = "nickname";
private static final String ATTR_USER_FLAGS = "userFlags";
private static final String ATTR_CREATED_MILLIS = "createdMillis";
+ private static final String ATTR_LAST_SEEN_MILLIS = "lastSeenMillis";
private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
@@ -350,9 +344,6 @@
@GuardedBy("mLock")
private String mMoveTargetUuid;
- @GuardedBy("mPackagesLock")
- private final SparseArray<ArraySet<String>> mPackages = new SparseArray<>();
-
private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
/** Holding lock for AppFuse business */
@@ -469,14 +460,11 @@
private volatile IVold mVold;
private volatile IStoraged mStoraged;
- private volatile boolean mSystemReady = false;
private volatile boolean mBootCompleted = false;
private volatile boolean mDaemonConnected = false;
private volatile boolean mSecureKeyguardShowing = true;
private PackageManagerInternal mPmInternal;
- private UserManagerInternal mUmInternal;
- private ActivityManagerInternal mAmInternal;
private IPackageManager mIPackageManager;
private IAppOpsService mIAppOpsService;
@@ -965,7 +953,7 @@
mVold.onUserAdded(user.id, user.serialNumber);
}
for (int userId : systemUnlockedUsers) {
- sendUserStartedCallback(userId);
+ mVold.onUserStarted(userId);
mStoraged.onUserStarted(userId);
}
mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
@@ -983,7 +971,7 @@
// staging area is ready so it's ready for zygote-forked apps to
// bind mount against.
try {
- sendUserStartedCallback(userId);
+ mVold.onUserStarted(userId);
mStoraged.onUserStarted(userId);
} catch (Exception e) {
Slog.wtf(TAG, e);
@@ -1016,53 +1004,12 @@
Slog.wtf(TAG, e);
}
- synchronized (mPackagesLock) {
- mPackages.delete(userId);
- }
-
synchronized (mLock) {
mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
}
}
- private void sendUserStartedCallback(int userId) throws Exception {
- if (!ENABLE_ISOLATED_STORAGE) {
- mVold.onUserStarted(userId, EmptyArray.STRING, EmptyArray.INT, EmptyArray.STRING);
- }
-
- final String[] packages;
- final int[] appIds;
- final String[] sandboxIds;
- final SparseArray<String> sharedUserIds = mPmInternal.getAppsWithSharedUserIds();
- final List<ApplicationInfo> appInfos =
- mContext.getPackageManager().getInstalledApplicationsAsUser(
- PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
- synchronized (mPackagesLock) {
- final ArraySet<String> userPackages = new ArraySet<>();
- final ArrayMap<String, Integer> packageToAppId = new ArrayMap<>();
- for (int i = appInfos.size() - 1; i >= 0; --i) {
- final ApplicationInfo appInfo = appInfos.get(i);
- if (appInfo.isInstantApp()) {
- continue;
- }
- userPackages.add(appInfo.packageName);
- packageToAppId.put(appInfo.packageName, UserHandle.getAppId(appInfo.uid));
- }
- mPackages.put(userId, userPackages);
-
- packages = new String[userPackages.size()];
- appIds = new int[userPackages.size()];
- sandboxIds = new String[userPackages.size()];
- for (int i = userPackages.size() - 1; i >= 0; --i) {
- packages[i] = userPackages.valueAt(i);
- appIds[i] = packageToAppId.get(packages[i]);
- sandboxIds[i] = getSandboxId(packages[i], sharedUserIds.get(appIds[i]));
- }
- }
- mVold.onUserStarted(userId, packages, appIds, sandboxIds);
- }
-
- private boolean supportsBlockCheckpoint() throws RemoteException {
+ private boolean supportsBlockCheckpoint() throws RemoteException {
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
return mVold.supportsBlockCheckpoint();
}
@@ -1367,7 +1314,7 @@
private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
// Remember that we saw this volume so we're ready to accept user
// metadata, or so we can annoy them when a private volume is ejected
- if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
+ if (!TextUtils.isEmpty(vol.fsUuid)) {
VolumeRecord rec = mRecords.get(vol.fsUuid);
if (rec == null) {
rec = new VolumeRecord(vol.type, vol.fsUuid);
@@ -1377,14 +1324,15 @@
rec.nickname = vol.disk.getDescription();
}
mRecords.put(rec.fsUuid, rec);
- writeSettingsLocked();
} else {
// Handle upgrade case where we didn't store partition GUID
if (TextUtils.isEmpty(rec.partGuid)) {
rec.partGuid = vol.partGuid;
- writeSettingsLocked();
}
}
+
+ rec.lastSeenMillis = System.currentTimeMillis();
+ writeSettingsLocked();
}
mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
@@ -1596,11 +1544,6 @@
connect();
}
- private static String getSandboxId(String packageName, String sharedUserId) {
- return sharedUserId == null
- ? packageName : StorageManager.SHARED_SANDBOX_PREFIX + sharedUserId;
- }
-
private void connect() {
IBinder binder = ServiceManager.getService("storaged");
if (binder != null) {
@@ -1663,8 +1606,6 @@
private void servicesReady() {
mPmInternal = LocalServices.getService(PackageManagerInternal.class);
- mUmInternal = LocalServices.getService(UserManagerInternal.class);
- mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
mIPackageManager = IPackageManager.Stub.asInterface(
ServiceManager.getService("package"));
@@ -1694,7 +1635,6 @@
LocalServices.getService(ActivityTaskManagerInternal.class)
.registerScreenObserver(this);
- mSystemReady = true;
mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
}
@@ -1793,9 +1733,10 @@
meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
- meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
- meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
- meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
+ meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0);
+ meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0);
+ meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0);
+ meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0);
return meta;
}
@@ -1807,6 +1748,7 @@
writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
+ writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis);
writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
out.endTag(null, TAG_VOLUME);
@@ -2994,7 +2936,6 @@
@Override
public void mkdirs(String callingPkg, String appPath) {
- final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final int userId = UserHandle.getUserId(callingUid);
final UserEnvironment userEnv = new UserEnvironment(userId);
@@ -3033,13 +2974,11 @@
appPath = appPath + "/";
}
- final String systemPath = translateAppToSystem(appPath, callingPid, callingUid);
-
try {
- mVold.mkdirs(systemPath);
+ mVold.mkdirs(appPath);
return;
} catch (Exception e) {
- throw new IllegalStateException("Failed to prepare " + systemPath + ": " + e);
+ throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
}
}
@@ -3307,75 +3246,6 @@
}
};
- private static final Pattern PATTERN_TRANSLATE = Pattern.compile(
- "(?i)^(/storage/[^/]+/(?:[0-9]+/)?)(.*)");
-
- @Override
- public String translateAppToSystem(String path, int pid, int uid) {
- return translateInternal(path, pid, uid, true);
- }
-
- @Override
- public String translateSystemToApp(String path, int pid, int uid) {
- return translateInternal(path, pid, uid, false);
- }
-
- private String translateInternal(String path, int pid, int uid, boolean toSystem) {
- if (true) return path;
-
- if (path.contains("/../")) {
- throw new SecurityException("Shady looking path " + path);
- }
-
- final int mountMode = mAmInternal.getStorageMountMode(pid, uid);
- if (mountMode == Zygote.MOUNT_EXTERNAL_FULL
- || mountMode == Zygote.MOUNT_EXTERNAL_LEGACY) {
- return path;
- }
-
- final Matcher m = PATTERN_TRANSLATE.matcher(path);
- if (m.matches()) {
- final String device = m.group(1);
- final String devicePath = m.group(2);
-
- if (mountMode == Zygote.MOUNT_EXTERNAL_INSTALLER
- && devicePath.startsWith("Android/obb/")) {
- return path;
- }
-
- // Does path belong to any packages belonging to this UID? If so,
- // they get to go straight through to legacy paths.
- final String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
- for (String pkg : pkgs) {
- if (devicePath.startsWith("Android/data/" + pkg + "/") ||
- devicePath.startsWith("Android/media/" + pkg + "/") ||
- devicePath.startsWith("Android/obb/" + pkg + "/")) {
- return path;
- }
- }
-
- final String sharedUserId = mPmInternal.getSharedUserIdForPackage(pkgs[0]);
- final String sandboxId = getSandboxId(pkgs[0], sharedUserId);
-
- if (toSystem) {
- // Everything else goes into sandbox.
- return device + "Android/sandbox/" + sandboxId + "/" + devicePath;
- } else {
- // Does path belong to this sandbox? If so, leave sandbox.
- final String sandboxPrefix = "Android/sandbox/" + sandboxId + "/";
- if (devicePath.startsWith(sandboxPrefix)) {
- return device + devicePath.substring(sandboxPrefix.length());
- }
-
- // Path isn't valid inside sandbox!
- throw new SecurityException(
- "Path " + path + " isn't valid inside sandbox " + sandboxId);
- }
- }
-
- return path;
- }
-
private void addObbStateLocked(ObbState obbState) throws RemoteException {
final IBinder binder = obbState.getBinder();
List<ObbState> obbStates = mObbMounts.get(binder);
@@ -4048,55 +3918,5 @@
}
return true;
}
-
- @Override
- public void prepareSandboxForApp(String packageName, int appId, String sharedUserId,
- int userId) {
- final String sandboxId;
- synchronized (mPackagesLock) {
- final ArraySet<String> userPackages = mPackages.get(userId);
- // If userPackages is empty, it means the user is not started yet, so no need to
- // do anything now.
- if (userPackages == null || userPackages.contains(packageName)) {
- return;
- }
- userPackages.add(packageName);
- sandboxId = StorageManagerService.this.getSandboxId(packageName, sharedUserId);
- }
-
- try {
- mVold.prepareSandboxForApp(packageName, appId, sandboxId, userId);
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- }
- }
-
- @Override
- public void destroySandboxForApp(String packageName, String sharedUserId, int userId) {
- if (!ENABLE_ISOLATED_STORAGE) {
- return;
- }
- final String sandboxId = StorageManagerService.this.getSandboxId(
- packageName, sharedUserId);
- synchronized (mPackagesLock) {
- final ArraySet<String> userPackages = mPackages.get(userId);
- // If the userPackages is null, it means the user is not started but we still
- // need to delete the sandbox data though.
- if (userPackages != null) {
- userPackages.remove(packageName);
- }
- }
- try {
- mVold.destroySandboxForApp(packageName, sandboxId, userId);
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- }
- }
-
- @Override
- public String getSandboxId(String packageName) {
- return StorageManagerService.this.getSandboxId(packageName,
- mPmInternal.getSharedUserIdForPackage(packageName));
- }
}
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 28bc348..1a6faec 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -201,7 +201,7 @@
private int[] mDataConnectionNetworkType;
- private int mOtaspMode = TelephonyManager.OTASP_UNKNOWN;
+ private int[] mOtaspMode;
private ArrayList<List<CellInfo>> mCellInfo = null;
@@ -209,13 +209,12 @@
private Map<Integer, List<EmergencyNumber>> mEmergencyNumberList;
- private CallQuality mCallQuality = new CallQuality();
+ private CallQuality[] mCallQuality;
- private CallAttributes mCallAttributes = new CallAttributes(new PreciseCallState(),
- TelephonyManager.NETWORK_TYPE_UNKNOWN, new CallQuality());
+ private CallAttributes[] mCallAttributes;
// network type of the call associated with the mCallAttributes and mCallQuality
- private int mCallNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ private int[] mCallNetworkType;
private int[] mSrvccState;
@@ -223,19 +222,19 @@
private int mDefaultPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
- private int mRingingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ private int[] mRingingCallState;
- private int mForegroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ private int[] mForegroundCallState;
- private int mBackgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ private int[] mBackgroundCallState;
- private PreciseCallState mPreciseCallState = new PreciseCallState();
+ private PreciseCallState[] mPreciseCallState;
- private int mCallDisconnectCause = DisconnectCause.NOT_VALID;
+ private int[] mCallDisconnectCause;
private List<ImsReasonInfo> mImsReasonInfo = null;
- private int mCallPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
+ private int[] mCallPreciseDisconnectCause;
private boolean mCarrierNetworkChangeState = false;
@@ -250,8 +249,7 @@
private final LocalLog mListenLog = new LocalLog(100);
- private PreciseDataConnectionState mPreciseDataConnectionState =
- new PreciseDataConnectionState();
+ private PreciseDataConnectionState[] mPreciseDataConnectionState;
// Nothing here yet, but putting it here in case we want to add more in the future.
static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK = 0;
@@ -342,7 +340,7 @@
Integer newDefaultSubIdObj = new Integer(intent.getIntExtra(
PhoneConstants.SUBSCRIPTION_KEY,
SubscriptionManager.getDefaultSubscriptionId()));
- int newDefaultPhoneId = intent.getIntExtra(PhoneConstants.SLOT_KEY,
+ int newDefaultPhoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY,
SubscriptionManager.getPhoneId(mDefaultSubId));
if (DBG) {
log("onReceive:current mDefaultSubId=" + mDefaultSubId
@@ -389,10 +387,21 @@
mMessageWaiting = new boolean[numPhones];
mCallForwarding = new boolean[numPhones];
mCellLocation = new Bundle[numPhones];
- mCellInfo = new ArrayList<List<CellInfo>>();
mSrvccState = new int[numPhones];
- mImsReasonInfo = new ArrayList<ImsReasonInfo>();
- mPhysicalChannelConfigs = new ArrayList<List<PhysicalChannelConfig>>();
+ mOtaspMode = new int[numPhones];
+ mPreciseCallState = new PreciseCallState[numPhones];
+ mForegroundCallState = new int[numPhones];
+ mBackgroundCallState = new int[numPhones];
+ mRingingCallState = new int[numPhones];
+ mCallDisconnectCause = new int[numPhones];
+ mCallPreciseDisconnectCause = new int[numPhones];
+ mCallQuality = new CallQuality[numPhones];
+ mCallNetworkType = new int[numPhones];
+ mCallAttributes = new CallAttributes[numPhones];
+ mPreciseDataConnectionState = new PreciseDataConnectionState[numPhones];
+ mCellInfo = new ArrayList<>();
+ mImsReasonInfo = new ArrayList<>();
+ mPhysicalChannelConfigs = new ArrayList<>();
mEmergencyNumberList = new HashMap<>();
for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
@@ -410,7 +419,19 @@
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
- mPhysicalChannelConfigs.add(i, new ArrayList<PhysicalChannelConfig>());
+ mPhysicalChannelConfigs.add(i, new ArrayList<>());
+ mOtaspMode[i] = TelephonyManager.OTASP_UNKNOWN;
+ mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
+ mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
+ mCallQuality[i] = new CallQuality();
+ mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, new CallQuality());
+ mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ mPreciseCallState[i] = new PreciseCallState();
+ mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ mPreciseDataConnectionState[i] = new PreciseDataConnectionState();
}
// Note that location can be null for non-phone builds like
@@ -731,7 +752,7 @@
}
if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
try {
- r.callback.onOtaspChanged(mOtaspMode);
+ r.callback.onOtaspChanged(mOtaspMode[phoneId]);
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -749,15 +770,15 @@
}
if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
try {
- r.callback.onPreciseCallStateChanged(mPreciseCallState);
+ r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]);
} catch (RemoteException ex) {
remove(r.binder);
}
}
if ((events & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
try {
- r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause,
- mCallPreciseDisconnectCause);
+ r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause[phoneId],
+ mCallPreciseDisconnectCause[phoneId]);
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -772,7 +793,7 @@
if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
try {
r.callback.onPreciseDataConnectionStateChanged(
- mPreciseDataConnectionState);
+ mPreciseDataConnectionState[phoneId]);
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -854,7 +875,7 @@
}
if ((events & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) {
try {
- r.callback.onCallAttributesChanged(mCallAttributes);
+ r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -1392,12 +1413,14 @@
LinkProperties linkProperties,
NetworkCapabilities networkCapabilities, int networkType,
boolean roaming) {
- notifyDataConnectionForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, state,
+ notifyDataConnectionForSubscriber(SubscriptionManager.DEFAULT_PHONE_INDEX,
+ SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, state,
isDataAllowed, apn, apnType, linkProperties,
networkCapabilities, networkType, roaming);
}
- public void notifyDataConnectionForSubscriber(int subId, int state, boolean isDataAllowed,
+ public void notifyDataConnectionForSubscriber(int phoneId, int subId, int state,
+ boolean isDataAllowed,
String apn, String apnType,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int networkType, boolean roaming) {
@@ -1410,7 +1433,6 @@
+ "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
+ " mRecords.size()=" + mRecords.size());
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
// We only call the callback when the change is for default APN type.
@@ -1425,8 +1447,8 @@
mLocalLog.log(str);
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) &&
- idMatch(r.subId, subId, phoneId)) {
+ PhoneStateListener.LISTEN_DATA_CONNECTION_STATE)
+ && idMatch(r.subId, subId, phoneId)) {
try {
if (DBG) {
log("Notify data connection state changed on sub: " + subId);
@@ -1442,15 +1464,17 @@
mDataConnectionState[phoneId] = state;
mDataConnectionNetworkType[phoneId] = networkType;
}
- mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
+ mPreciseDataConnectionState[phoneId] = new PreciseDataConnectionState(
+ state, networkType,
ApnSetting.getApnTypesBitmaskFromString(apnType), apn,
linkProperties, DataFailCause.NONE);
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
+ PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
+ && idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onPreciseDataConnectionStateChanged(
- mPreciseDataConnectionState);
+ mPreciseDataConnectionState[phoneId]);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -1466,11 +1490,12 @@
}
public void notifyDataConnectionFailed(String apnType) {
- notifyDataConnectionFailedForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ notifyDataConnectionFailedForSubscriber(SubscriptionManager.DEFAULT_PHONE_INDEX,
+ SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
apnType);
}
- public void notifyDataConnectionFailedForSubscriber(int subId, String apnType) {
+ public void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, String apnType) {
if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
return;
}
@@ -1479,20 +1504,25 @@
+ " apnType=" + apnType);
}
synchronized (mRecords) {
- mPreciseDataConnectionState = new PreciseDataConnectionState(
- TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN,
- ApnSetting.getApnTypesBitmaskFromString(apnType), null, null,
- DataFailCause.NONE);
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
- try {
- r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
+ if (validatePhoneId(phoneId)) {
+ mPreciseDataConnectionState[phoneId] = new PreciseDataConnectionState(
+ TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN,
+ ApnSetting.getApnTypesBitmaskFromString(apnType), null, null,
+ DataFailCause.NONE);
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onPreciseDataConnectionStateChanged(
+ mPreciseDataConnectionState[phoneId]);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
}
}
}
+
handleRemoveListLocked();
}
broadcastDataConnectionFailed(apnType, subId);
@@ -1539,18 +1569,22 @@
}
}
- public void notifyOtaspChanged(int otaspMode) {
+ public void notifyOtaspChanged(int subId, int otaspMode) {
if (!checkNotifyPermission("notifyOtaspChanged()" )) {
return;
}
+ int phoneId = SubscriptionManager.getPhoneId(subId);
synchronized (mRecords) {
- mOtaspMode = otaspMode;
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_OTASP_CHANGED)) {
- try {
- r.callback.onOtaspChanged(otaspMode);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
+ if (validatePhoneId(phoneId)) {
+ mOtaspMode[phoneId] = otaspMode;
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_OTASP_CHANGED)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onOtaspChanged(otaspMode);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
}
}
}
@@ -1558,49 +1592,55 @@
}
}
- public void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
- int backgroundCallState, int phoneId) {
+ public void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
+ int foregroundCallState, int backgroundCallState) {
if (!checkNotifyPermission("notifyPreciseCallState()")) {
return;
}
synchronized (mRecords) {
- mRingingCallState = ringingCallState;
- mForegroundCallState = foregroundCallState;
- mBackgroundCallState = backgroundCallState;
- mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState,
- backgroundCallState,
- DisconnectCause.NOT_VALID,
- PreciseDisconnectCause.NOT_VALID);
- boolean notifyCallAttributes = true;
- if (mCallQuality == null) {
- log("notifyPreciseCallState: mCallQuality is null, skipping call attributes");
- notifyCallAttributes = false;
- } else {
- // If the precise call state is no longer active, reset the call network type and
- // call quality.
- if (mPreciseCallState.getForegroundCallState()
- != PreciseCallState.PRECISE_CALL_STATE_ACTIVE) {
- mCallNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- mCallQuality = new CallQuality();
- }
- mCallAttributes = new CallAttributes(mPreciseCallState, mCallNetworkType,
- mCallQuality);
- }
-
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE)) {
- try {
- r.callback.onPreciseCallStateChanged(mPreciseCallState);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
+ if (validatePhoneId(phoneId)) {
+ mRingingCallState[phoneId] = ringingCallState;
+ mForegroundCallState[phoneId] = foregroundCallState;
+ mBackgroundCallState[phoneId] = backgroundCallState;
+ mPreciseCallState[phoneId] = new PreciseCallState(
+ ringingCallState, foregroundCallState,
+ backgroundCallState,
+ DisconnectCause.NOT_VALID,
+ PreciseDisconnectCause.NOT_VALID);
+ boolean notifyCallAttributes = true;
+ if (mCallQuality == null) {
+ log("notifyPreciseCallState: mCallQuality is null, "
+ + "skipping call attributes");
+ notifyCallAttributes = false;
+ } else {
+ // If the precise call state is no longer active, reset the call network type
+ // and call quality.
+ if (mPreciseCallState[phoneId].getForegroundCallState()
+ != PreciseCallState.PRECISE_CALL_STATE_ACTIVE) {
+ mCallNetworkType[phoneId] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ mCallQuality[phoneId] = new CallQuality();
}
+ mCallAttributes[phoneId] = new CallAttributes(mPreciseCallState[phoneId],
+ mCallNetworkType[phoneId], mCallQuality[phoneId]);
}
- if (notifyCallAttributes && r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)) {
- try {
- r.callback.onCallAttributesChanged(mCallAttributes);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
+
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ if (notifyCallAttributes && r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
}
}
}
@@ -1610,21 +1650,24 @@
backgroundCallState);
}
- public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) {
+ public void notifyDisconnectCause(int phoneId, int subId, int disconnectCause,
+ int preciseDisconnectCause) {
if (!checkNotifyPermission("notifyDisconnectCause()")) {
return;
}
synchronized (mRecords) {
- mCallDisconnectCause = disconnectCause;
- mCallPreciseDisconnectCause = preciseDisconnectCause;
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(PhoneStateListener
- .LISTEN_CALL_DISCONNECT_CAUSES)) {
- try {
- r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause,
- mCallPreciseDisconnectCause);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
+ if (validatePhoneId(phoneId)) {
+ mCallDisconnectCause[phoneId] = disconnectCause;
+ mCallPreciseDisconnectCause[phoneId] = preciseDisconnectCause;
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(PhoneStateListener
+ .LISTEN_CALL_DISCONNECT_CAUSES) && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause[phoneId],
+ mCallPreciseDisconnectCause[phoneId]);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
}
}
}
@@ -1660,25 +1703,30 @@
}
}
- public void notifyPreciseDataConnectionFailed(String apnType,
+ public void notifyPreciseDataConnectionFailed(int phoneId, int subId, String apnType,
String apn, @DataFailCause.FailCause int failCause) {
if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) {
return;
}
synchronized (mRecords) {
- mPreciseDataConnectionState = new PreciseDataConnectionState(
- TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- ApnSetting.getApnTypesBitmaskFromString(apnType), apn, null, failCause);
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
- try {
- r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
+ if (validatePhoneId(phoneId)) {
+ mPreciseDataConnectionState[phoneId] = new PreciseDataConnectionState(
+ TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN,
+ ApnSetting.getApnTypesBitmaskFromString(apnType), apn, null, failCause);
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onPreciseDataConnectionStateChanged(
+ mPreciseDataConnectionState[phoneId]);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
}
}
}
+
handleRemoveListLocked();
}
broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
@@ -1716,24 +1764,25 @@
}
}
- public void notifyOemHookRawEventForSubscriber(int subId, byte[] rawData) {
+ public void notifyOemHookRawEventForSubscriber(int phoneId, int subId, byte[] rawData) {
if (!checkNotifyPermission("notifyOemHookRawEventForSubscriber")) {
return;
}
synchronized (mRecords) {
- for (Record r : mRecords) {
- if (VDBG) {
- log("notifyOemHookRawEventForSubscriber: r=" + r + " subId=" + subId);
- }
- if ((r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT)) &&
- ((r.subId == subId) ||
- (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID))) {
- try {
- r.callback.onOemHookRawEvent(rawData);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
+ if (validatePhoneId(phoneId)) {
+ for (Record r : mRecords) {
+ if (VDBG) {
+ log("notifyOemHookRawEventForSubscriber: r=" + r + " subId=" + subId);
+ }
+ if ((r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT))
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onOemHookRawEvent(rawData);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
}
}
}
@@ -1804,87 +1853,98 @@
}
}
- public void notifyRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state) {
+ public void notifyRadioPowerStateChanged(int phoneId, int subId,
+ @TelephonyManager.RadioPowerState int state) {
if (!checkNotifyPermission("notifyRadioPowerStateChanged()")) {
return;
}
if (VDBG) {
- log("notifyRadioPowerStateChanged: state= " + state);
+ log("notifyRadioPowerStateChanged: state= " + state + " subId=" + subId);
}
synchronized (mRecords) {
- mRadioPowerState = state;
+ if (validatePhoneId(phoneId)) {
+ mRadioPowerState = state;
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED)) {
- try {
- r.callback.onRadioPowerStateChanged(state);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onRadioPowerStateChanged(state);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
}
}
+
}
handleRemoveListLocked();
}
}
@Override
- public void notifyEmergencyNumberList() {
+ public void notifyEmergencyNumberList(int phoneId, int subId) {
if (!checkNotifyPermission("notifyEmergencyNumberList()")) {
return;
}
synchronized (mRecords) {
- TelephonyManager tm = (TelephonyManager) mContext.getSystemService(
- Context.TELEPHONY_SERVICE);
- mEmergencyNumberList = tm.getEmergencyNumberList();
+ if (validatePhoneId(phoneId)) {
+ TelephonyManager tm = (TelephonyManager) mContext.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ mEmergencyNumberList = tm.getEmergencyNumberList();
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST)) {
- try {
- r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
- if (VDBG) {
- log("notifyEmergencyNumberList: emergencyNumberList= "
- + mEmergencyNumberList);
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
+ if (VDBG) {
+ log("notifyEmergencyNumberList: emergencyNumberList= "
+ + mEmergencyNumberList);
+ }
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
}
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
}
}
}
+
handleRemoveListLocked();
}
}
@Override
- public void notifyCallQualityChanged(CallQuality callQuality, int phoneId,
+ public void notifyCallQualityChanged(CallQuality callQuality, int phoneId, int subId,
int callNetworkType) {
if (!checkNotifyPermission("notifyCallQualityChanged()")) {
return;
}
- // merge CallQuality with PreciseCallState and network type
- mCallQuality = callQuality;
- mCallNetworkType = callNetworkType;
- mCallAttributes = new CallAttributes(mPreciseCallState, callNetworkType, callQuality);
-
synchronized (mRecords) {
- TelephonyManager tm = (TelephonyManager) mContext.getSystemService(
- Context.TELEPHONY_SERVICE);
+ if (validatePhoneId(phoneId)) {
+ // merge CallQuality with PreciseCallState and network type
+ mCallQuality[phoneId] = callQuality;
+ mCallNetworkType[phoneId] = callNetworkType;
+ mCallAttributes[phoneId] = new CallAttributes(mPreciseCallState[phoneId],
+ callNetworkType, callQuality);
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)) {
- try {
- r.callback.onCallAttributesChanged(mCallAttributes);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
}
}
}
+
handleRemoveListLocked();
}
}
@@ -1904,6 +1964,11 @@
pw.println("Phone Id=" + i);
pw.increaseIndent();
pw.println("mCallState=" + mCallState[i]);
+ pw.println("mRingingCallState=" + mRingingCallState[i]);
+ pw.println("mForegroundCallState=" + mForegroundCallState[i]);
+ pw.println("mBackgroundCallState=" + mBackgroundCallState[i]);
+ pw.println("mPreciseCallState=" + mPreciseCallState[i]);
+ pw.println("mCallDisconnectCause=" + mCallDisconnectCause[i]);
pw.println("mCallIncomingNumber=" + mCallIncomingNumber[i]);
pw.println("mServiceState=" + mServiceState[i]);
pw.println("mVoiceActivationState= " + mVoiceActivationState[i]);
@@ -1917,26 +1982,23 @@
pw.println("mCellLocation=" + mCellLocation[i]);
pw.println("mCellInfo=" + mCellInfo.get(i));
pw.println("mImsCallDisconnectCause=" + mImsReasonInfo.get(i));
+ pw.println("mSrvccState=" + mSrvccState[i]);
+ pw.println("mOtaspMode=" + mOtaspMode[i]);
+ pw.println("mCallPreciseDisconnectCause=" + mCallPreciseDisconnectCause[i]);
+ pw.println("mCallQuality=" + mCallQuality[i]);
+ pw.println("mCallAttributes=" + mCallAttributes[i]);
+ pw.println("mCallNetworkType=" + mCallNetworkType[i]);
+ pw.println("mPreciseDataConnectionState=" + mPreciseDataConnectionState[i]);
pw.decreaseIndent();
}
- pw.println("mCallNetworkType=" + mCallNetworkType);
- pw.println("mPreciseDataConnectionState=" + mPreciseDataConnectionState);
- pw.println("mPreciseCallState=" + mPreciseCallState);
- pw.println("mCallDisconnectCause=" + mCallDisconnectCause);
- pw.println("mCallPreciseDisconnectCause=" + mCallPreciseDisconnectCause);
pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
- pw.println("mRingingCallState=" + mRingingCallState);
- pw.println("mForegroundCallState=" + mForegroundCallState);
- pw.println("mBackgroundCallState=" + mBackgroundCallState);
- pw.println("mSrvccState=" + mSrvccState);
+
pw.println("mPhoneCapability=" + mPhoneCapability);
pw.println("mActiveDataSubId=" + mActiveDataSubId);
pw.println("mRadioPowerState=" + mRadioPowerState);
pw.println("mEmergencyNumberList=" + mEmergencyNumberList);
- pw.println("mCallQuality=" + mCallQuality);
- pw.println("mCallAttributes=" + mCallAttributes);
- pw.println("mDefaultPhoneId" + mDefaultPhoneId);
- pw.println("mDefaultSubId" + mDefaultSubId);
+ pw.println("mDefaultPhoneId=" + mDefaultPhoneId);
+ pw.println("mDefaultSubId=" + mDefaultSubId);
pw.decreaseIndent();
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 3a50aa8..0eb3a84 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -33,6 +33,8 @@
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.net.Uri;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Handler;
@@ -45,7 +47,7 @@
import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.UserHandle;
-import android.provider.Settings;
+import android.provider.Settings.Secure;
import android.service.dreams.Sandman;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
@@ -87,6 +89,7 @@
private boolean mVrHeadset;
private boolean mComputedNightMode;
private int mCarModeEnableFlags;
+ private boolean mSetupWizardComplete;
// flag set by resource, whether to enable Car dock launch when starting car mode.
private boolean mEnableCarDockLaunch = true;
@@ -196,6 +199,29 @@
}
};
+ private final ContentObserver mSetupWizardObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ // setup wizard is done now so we can unblock
+ if (setupWizardCompleteForCurrentUser()) {
+ mSetupWizardComplete = true;
+ getContext().getContentResolver().unregisterContentObserver(mSetupWizardObserver);
+ // update night mode
+ Context context = getContext();
+ updateNightModeFromSettings(context, context.getResources(),
+ UserHandle.getCallingUserId());
+ updateLocked(0, 0);
+ }
+ }
+ };
+
+ @Override
+ public void onSwitchUser(int userHandle) {
+ super.onSwitchUser(userHandle);
+ getContext().getContentResolver().unregisterContentObserver(mSetupWizardObserver);
+ verifySetupWizardCompleted();
+ }
+
@Override
public void onStart() {
final Context context = getContext();
@@ -204,6 +230,10 @@
(PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
+ // If setup isn't complete for this user listen for completion so we can unblock
+ // being able to send a night mode configuration change event
+ verifySetupWizardCompleted();
+
context.registerReceiver(mDockModeReceiver,
new IntentFilter(Intent.ACTION_DOCK_EVENT));
IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
@@ -262,6 +292,25 @@
context.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
}
+ // Records whether setup wizard has happened or not and adds an observer for this user if not.
+ private void verifySetupWizardCompleted() {
+ final Context context = getContext();
+ final int userId = UserHandle.getCallingUserId();
+ if (!setupWizardCompleteForCurrentUser()) {
+ mSetupWizardComplete = false;
+ context.getContentResolver().registerContentObserver(
+ Secure.getUriFor(
+ Secure.USER_SETUP_COMPLETE), false, mSetupWizardObserver, userId);
+ } else {
+ mSetupWizardComplete = true;
+ }
+ }
+
+ private boolean setupWizardCompleteForCurrentUser() {
+ return Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.USER_SETUP_COMPLETE, 0, UserHandle.getCallingUserId()) == 1;
+ }
+
/**
* Updates the night mode setting in Settings.Global and returns if the value was successfully
* changed.
@@ -274,8 +323,12 @@
final int defaultNightMode = res.getInteger(
com.android.internal.R.integer.config_defaultNightMode);
int oldNightMode = mNightMode;
- mNightMode = Settings.Secure.getIntForUser(context.getContentResolver(),
- Settings.Secure.UI_NIGHT_MODE, defaultNightMode, userId);
+ if (mSetupWizardComplete) {
+ mNightMode = Secure.getIntForUser(context.getContentResolver(),
+ Secure.UI_NIGHT_MODE, defaultNightMode, userId);
+ } else {
+ mNightMode = defaultNightMode;
+ }
// false if night mode stayed the same, true otherwise.
return !(oldNightMode == mNightMode);
@@ -340,6 +393,10 @@
Slog.e(TAG, "Night mode locked, requires MODIFY_DAY_NIGHT_MODE permission");
return;
}
+ if (!mSetupWizardComplete) {
+ Slog.d(TAG, "Night mode cannot be changed before setup wizard completes.");
+ return;
+ }
switch (mode) {
case UiModeManager.MODE_NIGHT_NO:
case UiModeManager.MODE_NIGHT_YES:
@@ -356,8 +413,8 @@
if (mNightMode != mode) {
// Only persist setting if not in car mode
if (!mCarModeEnabled) {
- Settings.Secure.putIntForUser(getContext().getContentResolver(),
- Settings.Secure.UI_NIGHT_MODE, mode, user);
+ Secure.putIntForUser(getContext().getContentResolver(),
+ Secure.UI_NIGHT_MODE, mode, user);
}
mNightMode = mode;
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index f9aaf11..a7fb99f 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -140,6 +140,7 @@
private boolean mCompleted;
private Monitor mCurrentMonitor;
private long mStartTime;
+ private int mPauseCount;
HandlerChecker(Handler handler, String name, long waitMaxMillis) {
mHandler = handler;
@@ -160,17 +161,18 @@
mMonitors.addAll(mMonitorQueue);
mMonitorQueue.clear();
}
- if (mMonitors.size() == 0 && mHandler.getLooper().getQueue().isPolling()) {
+ if ((mMonitors.size() == 0 && mHandler.getLooper().getQueue().isPolling())
+ || (mPauseCount > 0)) {
+ // Don't schedule until after resume OR
// If the target looper has recently been polling, then
// there is no reason to enqueue our checker on it since that
// is as good as it not being deadlocked. This avoid having
- // to do a context switch to check the thread. Note that we
- // only do this if mCheckReboot is false and we have no
- // monitors, since those would need to be executed at this point.
+ // to do a context switch to check the thread. Note that we
+ // only do this if we have no monitors since those would need to
+ // be executed at this point.
mCompleted = true;
return;
}
-
if (!mCompleted) {
// we already have a check in flight, so no need
return;
@@ -236,6 +238,28 @@
mCurrentMonitor = null;
}
}
+
+ /** Pause the HandlerChecker. */
+ public void pauseLocked(String reason) {
+ mPauseCount++;
+ // Mark as completed, because there's a chance we called this after the watchog
+ // thread loop called Object#wait after 'WAITED_HALF'. In that case we want to ensure
+ // the next call to #getCompletionStateLocked for this checker returns 'COMPLETED'
+ mCompleted = true;
+ Slog.i(TAG, "Pausing HandlerChecker: " + mName + " for reason: "
+ + reason + ". Pause count: " + mPauseCount);
+ }
+
+ /** Resume the HandlerChecker from the last {@link #pauseLocked}. */
+ public void resumeLocked(String reason) {
+ if (mPauseCount > 0) {
+ mPauseCount--;
+ Slog.i(TAG, "Resuming HandlerChecker: " + mName + " for reason: "
+ + reason + ". Pause count: " + mPauseCount);
+ } else {
+ Slog.wtf(TAG, "Already resumed HandlerChecker: " + mName);
+ }
+ }
}
final class RebootRequestReceiver extends BroadcastReceiver {
@@ -364,6 +388,51 @@
}
/**
+ * Pauses Watchdog action for the currently running thread. Useful before executing long running
+ * operations that could falsely trigger the watchdog. Each call to this will require a matching
+ * call to {@link #resumeWatchingCurrentThread}.
+ *
+ * <p>If the current thread has not been added to the Watchdog, this call is a no-op.
+ *
+ * <p>If the Watchdog is already paused for the current thread, this call adds
+ * adds another pause and will require an additional {@link #resumeCurrentThread} to resume.
+ *
+ * <p>Note: Use with care, as any deadlocks on the current thread will be undetected until all
+ * pauses have been resumed.
+ */
+ public void pauseWatchingCurrentThread(String reason) {
+ synchronized (this) {
+ for (HandlerChecker hc : mHandlerCheckers) {
+ if (Thread.currentThread().equals(hc.getThread())) {
+ hc.pauseLocked(reason);
+ }
+ }
+ }
+ }
+
+ /**
+ * Resumes the last pause from {@link #pauseWatchingCurrentThread} for the currently running
+ * thread.
+ *
+ * <p>If the current thread has not been added to the Watchdog, this call is a no-op.
+ *
+ * <p>If the Watchdog action for the current thread is already resumed, this call logs a wtf.
+ *
+ * <p>If all pauses have been resumed, the Watchdog action is finally resumed, otherwise,
+ * the Watchdog action for the current thread remains paused until resume is called at least
+ * as many times as the calls to pause.
+ */
+ public void resumeWatchingCurrentThread(String reason) {
+ synchronized (this) {
+ for (HandlerChecker hc : mHandlerCheckers) {
+ if (Thread.currentThread().equals(hc.getThread())) {
+ hc.resumeLocked(reason);
+ }
+ }
+ }
+ }
+
+ /**
* Perform a full reboot of the system.
*/
void rebootSystem(String reason) {
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index 9325d25..bdbff3d 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -27,9 +27,11 @@
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.debug.AdbProtoEnums;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
+import android.net.Uri;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
@@ -48,6 +50,7 @@
import android.util.Xml;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.dump.DualDumpOutputStream;
@@ -57,18 +60,24 @@
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Provides communication to the Android Debug Bridge daemon to allow, deny, or clear public keysi
@@ -85,19 +94,22 @@
// This file contains keys that will be allowed to connect without user interaction as long
// as a subsequent connection occurs within the allowed duration.
private static final String ADB_TEMP_KEYS_FILE = "adb_temp_keys.xml";
- private static final int BUFFER_SIZE = 4096;
+ private static final int BUFFER_SIZE = 65536;
private final Context mContext;
private final Handler mHandler;
private AdbDebuggingThread mThread;
private boolean mAdbEnabled = false;
private String mFingerprints;
- private String mConnectedKey;
+ private final List<String> mConnectedKeys;
private String mConfirmComponent;
+ private final File mTestUserKeyFile;
public AdbDebuggingManager(Context context) {
mHandler = new AdbDebuggingHandler(FgThread.get().getLooper());
mContext = context;
+ mTestUserKeyFile = null;
+ mConnectedKeys = new ArrayList<>(1);
}
/**
@@ -105,10 +117,12 @@
* an adb connection from the key.
*/
@TestApi
- protected AdbDebuggingManager(Context context, String confirmComponent) {
+ protected AdbDebuggingManager(Context context, String confirmComponent, File testUserKeyFile) {
mHandler = new AdbDebuggingHandler(FgThread.get().getLooper());
mContext = context;
mConfirmComponent = confirmComponent;
+ mTestUserKeyFile = testUserKeyFile;
+ mConnectedKeys = new ArrayList<>();
}
class AdbDebuggingThread extends Thread {
@@ -153,12 +167,13 @@
mInputStream = null;
if (DEBUG) Slog.d(TAG, "Creating socket");
- mSocket = new LocalSocket();
+ mSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
mSocket.connect(address);
mOutputStream = mSocket.getOutputStream();
mInputStream = mSocket.getInputStream();
} catch (IOException ioe) {
+ Slog.e(TAG, "Caught an exception opening the socket: " + ioe);
closeSocketLocked();
throw ioe;
}
@@ -172,6 +187,7 @@
// if less than 2 bytes are read the if statements below will throw an
// IndexOutOfBoundsException.
if (count < 2) {
+ Slog.w(TAG, "Read failed with count " + count);
break;
}
@@ -183,9 +199,18 @@
msg.obj = key;
mHandler.sendMessage(msg);
} else if (buffer[0] == 'D' && buffer[1] == 'C') {
- Slog.d(TAG, "Received disconnected message");
+ String key = new String(Arrays.copyOfRange(buffer, 2, count));
+ Slog.d(TAG, "Received disconnected message: " + key);
Message msg = mHandler.obtainMessage(
AdbDebuggingHandler.MESSAGE_ADB_DISCONNECT);
+ msg.obj = key;
+ mHandler.sendMessage(msg);
+ } else if (buffer[0] == 'C' && buffer[1] == 'K') {
+ String key = new String(Arrays.copyOfRange(buffer, 2, count));
+ Slog.d(TAG, "Received connected key message: " + key);
+ Message msg = mHandler.obtainMessage(
+ AdbDebuggingHandler.MESSAGE_ADB_CONNECTED_KEY);
+ msg.obj = key;
mHandler.sendMessage(msg);
} else {
Slog.e(TAG, "Wrong message: "
@@ -243,14 +268,13 @@
}
class AdbDebuggingHandler extends Handler {
- // The time to schedule the job to keep the key store updated with a currently connected
- // key. This job is required because a deveoper could keep a device connected to their
- // system beyond the time within which a subsequent connection is allowed. But since the
- // last connection time is only written when a device is connected and disconnected then
- // if the device is rebooted while connected to the development system it would appear as
- // though the adb grant for the system is no longer authorized and the developer would need
- // to manually allow the connection again.
- private static final long UPDATE_KEY_STORE_JOB_INTERVAL = 86400000;
+ // The default time to schedule the job to keep the keystore updated with a currently
+ // connected key as well as to removed expired keys.
+ static final long UPDATE_KEYSTORE_JOB_INTERVAL = 86400000;
+ // The minimum interval at which the job should run to update the keystore. This is intended
+ // to prevent the job from running too often if the allowed connection time for adb grants
+ // is set to an extremely small value.
+ static final long UPDATE_KEYSTORE_MIN_JOB_INTERVAL = 60000;
static final int MESSAGE_ADB_ENABLED = 1;
static final int MESSAGE_ADB_DISABLED = 2;
@@ -259,11 +283,21 @@
static final int MESSAGE_ADB_CONFIRM = 5;
static final int MESSAGE_ADB_CLEAR = 6;
static final int MESSAGE_ADB_DISCONNECT = 7;
- static final int MESSAGE_ADB_PERSIST_KEY_STORE = 8;
- static final int MESSAGE_ADB_UPDATE_KEY_CONNECTION_TIME = 9;
+ static final int MESSAGE_ADB_PERSIST_KEYSTORE = 8;
+ static final int MESSAGE_ADB_UPDATE_KEYSTORE = 9;
+ static final int MESSAGE_ADB_CONNECTED_KEY = 10;
private AdbKeyStore mAdbKeyStore;
+ private ContentObserver mAuthTimeObserver = new ContentObserver(this) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ Slog.d(TAG, "Received notification that uri " + uri
+ + " was modified; rescheduling keystore job");
+ scheduleJobToUpdateAdbKeyStore();
+ }
+ };
+
AdbDebuggingHandler(Looper looper) {
super(looper);
}
@@ -285,13 +319,15 @@
if (mAdbEnabled) {
break;
}
-
+ registerForAuthTimeChanges();
mAdbEnabled = true;
mThread = new AdbDebuggingThread();
mThread.start();
mAdbKeyStore = new AdbKeyStore();
+ mAdbKeyStore.updateKeyStore();
+ scheduleJobToUpdateAdbKeyStore();
break;
case MESSAGE_ADB_DISABLED:
@@ -306,14 +342,20 @@
mThread = null;
}
- cancelJobToUpdateAdbKeyStore();
- mConnectedKey = null;
+ if (!mConnectedKeys.isEmpty()) {
+ for (String connectedKey : mConnectedKeys) {
+ mAdbKeyStore.setLastConnectionTime(connectedKey,
+ System.currentTimeMillis());
+ }
+ sendPersistKeyStoreMessage();
+ mConnectedKeys.clear();
+ }
+ scheduleJobToUpdateAdbKeyStore();
break;
case MESSAGE_ADB_ALLOW: {
String key = (String) msg.obj;
String fingerprints = getFingerprints(key);
-
if (!fingerprints.equals(mFingerprints)) {
Slog.e(TAG, "Fingerprints do not match. Got "
+ fingerprints + ", expected " + mFingerprints);
@@ -324,12 +366,12 @@
if (mThread != null) {
mThread.sendResponse("OK");
if (alwaysAllow) {
- mConnectedKey = key;
+ if (!mConnectedKeys.contains(key)) {
+ mConnectedKeys.add(key);
+ }
mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
+ sendPersistKeyStoreMessage();
scheduleJobToUpdateAdbKeyStore();
- // write this key to adb_keys as well so that subsequent connections can
- // go through the expected SIGNATURE interaction.
- writeKey(key);
}
logAdbConnectionChanged(key, AdbProtoEnums.USER_ALLOWED, alwaysAllow);
}
@@ -369,47 +411,129 @@
}
case MESSAGE_ADB_CLEAR: {
- deleteKeyFile();
- mConnectedKey = null;
+ Slog.d(TAG, "Received a request to clear the adb authorizations");
+ mConnectedKeys.clear();
mAdbKeyStore.deleteKeyStore();
cancelJobToUpdateAdbKeyStore();
break;
}
case MESSAGE_ADB_DISCONNECT: {
- if (mConnectedKey != null) {
- mAdbKeyStore.setLastConnectionTime(mConnectedKey,
- System.currentTimeMillis());
- cancelJobToUpdateAdbKeyStore();
+ String key = (String) msg.obj;
+ boolean alwaysAllow = false;
+ if (key != null && key.length() > 0) {
+ if (mConnectedKeys.contains(key)) {
+ alwaysAllow = true;
+ mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
+ sendPersistKeyStoreMessage();
+ scheduleJobToUpdateAdbKeyStore();
+ mConnectedKeys.remove(key);
+ }
+ } else {
+ Slog.w(TAG, "Received a disconnected key message with an empty key");
}
- logAdbConnectionChanged(mConnectedKey, AdbProtoEnums.DISCONNECTED,
- (mConnectedKey != null));
- mConnectedKey = null;
+ logAdbConnectionChanged(key, AdbProtoEnums.DISCONNECTED, alwaysAllow);
break;
}
- case MESSAGE_ADB_PERSIST_KEY_STORE: {
- mAdbKeyStore.persistKeyStore();
+ case MESSAGE_ADB_PERSIST_KEYSTORE: {
+ if (mAdbKeyStore != null) {
+ mAdbKeyStore.persistKeyStore();
+ }
break;
}
- case MESSAGE_ADB_UPDATE_KEY_CONNECTION_TIME: {
- if (mConnectedKey != null) {
- mAdbKeyStore.setLastConnectionTime(mConnectedKey,
- System.currentTimeMillis());
+ case MESSAGE_ADB_UPDATE_KEYSTORE: {
+ if (!mConnectedKeys.isEmpty()) {
+ for (String connectedKey : mConnectedKeys) {
+ mAdbKeyStore.setLastConnectionTime(connectedKey,
+ System.currentTimeMillis());
+ }
+ sendPersistKeyStoreMessage();
scheduleJobToUpdateAdbKeyStore();
+ } else if (!mAdbKeyStore.isEmpty()) {
+ mAdbKeyStore.updateKeyStore();
+ scheduleJobToUpdateAdbKeyStore();
+ }
+ break;
+ }
+
+ case MESSAGE_ADB_CONNECTED_KEY: {
+ String key = (String) msg.obj;
+ if (key == null || key.length() == 0) {
+ Slog.w(TAG, "Received a connected key message with an empty key");
+ } else {
+ if (!mConnectedKeys.contains(key)) {
+ mConnectedKeys.add(key);
+ }
+ mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
+ sendPersistKeyStoreMessage();
+ scheduleJobToUpdateAdbKeyStore();
+ logAdbConnectionChanged(key, AdbProtoEnums.AUTOMATICALLY_ALLOWED, true);
}
break;
}
}
}
+ void registerForAuthTimeChanges() {
+ Uri uri = Settings.Global.getUriFor(Settings.Global.ADB_ALLOWED_CONNECTION_TIME);
+ mContext.getContentResolver().registerContentObserver(uri, false, mAuthTimeObserver);
+ }
+
private void logAdbConnectionChanged(String key, int state, boolean alwaysAllow) {
long lastConnectionTime = mAdbKeyStore.getLastConnectionTime(key);
long authWindow = mAdbKeyStore.getAllowedConnectionTime();
+ Slog.d(TAG,
+ "Logging key " + key + ", state = " + state + ", alwaysAllow = " + alwaysAllow
+ + ", lastConnectionTime = " + lastConnectionTime + ", authWindow = "
+ + authWindow);
StatsLog.write(StatsLog.ADB_CONNECTION_CHANGED, lastConnectionTime, authWindow, state,
alwaysAllow);
}
+
+
+ /**
+ * Schedules a job to update the connection time of the currently connected key and filter
+ * out any keys that are beyond their expiration time.
+ *
+ * @return the time in ms when the next job will run or -1 if the job should not be
+ * scheduled to run.
+ */
+ @VisibleForTesting
+ long scheduleJobToUpdateAdbKeyStore() {
+ cancelJobToUpdateAdbKeyStore();
+ long keyExpiration = mAdbKeyStore.getNextExpirationTime();
+ // if the keyExpiration time is -1 then either the keys are set to never expire or
+ // there are no keys in the keystore, just return for now as a new job will be
+ // scheduled on the next connection or when the auth time changes.
+ if (keyExpiration == -1) {
+ return -1;
+ }
+ long delay;
+ // if the keyExpiration is 0 this indicates a key has already expired; schedule the job
+ // to run now to ensure the key is removed immediately from adb_keys.
+ if (keyExpiration == 0) {
+ delay = 0;
+ } else {
+ // else the next job should be run either daily or when the next key is set to
+ // expire with a min job interval to ensure this job does not run too often if a
+ // small value is set for the key expiration.
+ delay = Math.max(Math.min(UPDATE_KEYSTORE_JOB_INTERVAL, keyExpiration),
+ UPDATE_KEYSTORE_MIN_JOB_INTERVAL);
+ }
+ Message message = obtainMessage(MESSAGE_ADB_UPDATE_KEYSTORE);
+ sendMessageDelayed(message, delay);
+ return delay;
+ }
+
+ /**
+ * Cancels the scheduled job to update the connection time of the currently connected key
+ * and to remove any expired keys.
+ */
+ private void cancelJobToUpdateAdbKeyStore() {
+ removeMessages(AdbDebuggingHandler.MESSAGE_ADB_UPDATE_KEYSTORE);
+ }
}
private String getFingerprints(String key) {
@@ -534,7 +658,13 @@
}
File getUserKeyFile() {
- return getAdbFile(ADB_KEYS_FILE);
+ return mTestUserKeyFile == null ? getAdbFile(ADB_KEYS_FILE) : mTestUserKeyFile;
+ }
+
+ private void createKeyFile(File keyFile) throws IOException {
+ keyFile.createNewFile();
+ FileUtils.setPermissions(keyFile.toString(),
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1);
}
private void writeKey(String key) {
@@ -546,9 +676,7 @@
}
if (!keyFile.exists()) {
- keyFile.createNewFile();
- FileUtils.setPermissions(keyFile.toString(),
- FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1);
+ createKeyFile(keyFile);
}
FileOutputStream fo = new FileOutputStream(keyFile, true);
@@ -560,6 +688,35 @@
}
}
+ private void writeKeys(Iterable<String> keys) {
+ AtomicFile atomicKeyFile = null;
+ FileOutputStream fo = null;
+ try {
+ File keyFile = getUserKeyFile();
+
+ if (keyFile == null) {
+ return;
+ }
+
+ if (!keyFile.exists()) {
+ createKeyFile(keyFile);
+ }
+
+ atomicKeyFile = new AtomicFile(keyFile);
+ fo = atomicKeyFile.startWrite();
+ for (String key : keys) {
+ fo.write(key.getBytes());
+ fo.write('\n');
+ }
+ atomicKeyFile.finishWrite(fo);
+ } catch (IOException ex) {
+ Slog.e(TAG, "Error writing keys: " + ex);
+ if (atomicKeyFile != null) {
+ atomicKeyFile.failWrite(fo);
+ }
+ }
+ }
+
private void deleteKeyFile() {
File keyFile = getUserKeyFile();
if (keyFile != null) {
@@ -604,36 +761,14 @@
}
/**
- * Sends a message to the handler to persist the key store.
+ * Sends a message to the handler to persist the keystore.
*/
private void sendPersistKeyStoreMessage() {
- Message msg = mHandler.obtainMessage(AdbDebuggingHandler.MESSAGE_ADB_PERSIST_KEY_STORE);
+ Message msg = mHandler.obtainMessage(AdbDebuggingHandler.MESSAGE_ADB_PERSIST_KEYSTORE);
mHandler.sendMessage(msg);
}
/**
- * Schedules a job to update the connection time of the currently connected key. This is
- * intended for cases such as development devices that are left connected to a user's
- * system beyond the window within which a connection is allowed without user interaction.
- * A job should be rescheduled daily so that if the device is rebooted while connected to
- * the user's system the last time in the key store will show within 24 hours which should
- * be within the allowed window.
- */
- private void scheduleJobToUpdateAdbKeyStore() {
- Message message = mHandler.obtainMessage(
- AdbDebuggingHandler.MESSAGE_ADB_UPDATE_KEY_CONNECTION_TIME);
- mHandler.sendMessageDelayed(message, AdbDebuggingHandler.UPDATE_KEY_STORE_JOB_INTERVAL);
- }
-
- /**
- * Cancels the scheduled job to update the connection time of the currently connected key.
- * This should be invoked once the adb session is disconnected.
- */
- private void cancelJobToUpdateAdbKeyStore() {
- mHandler.removeMessages(AdbDebuggingHandler.MESSAGE_ADB_UPDATE_KEY_CONNECTION_TIME);
- }
-
- /**
* Dump the USB debugging state.
*/
public void dump(DualDumpOutputStream dump, String idName, long id) {
@@ -657,6 +792,13 @@
Slog.e(TAG, "Cannot read system keys", e);
}
+ try {
+ dump.write("keystore", AdbDebuggingManagerProto.KEYSTORE,
+ FileUtils.readTextFile(getAdbTempKeysFile(), 0, null));
+ } catch (IOException e) {
+ Slog.e(TAG, "Cannot read keystore: ", e);
+ }
+
dump.end(token);
}
@@ -667,11 +809,14 @@
*/
class AdbKeyStore {
private Map<String, Long> mKeyMap;
+ private Set<String> mSystemKeys;
private File mKeyFile;
private AtomicFile mAtomicKeyFile;
+
private static final String XML_TAG_ADB_KEY = "adbKey";
private static final String XML_ATTRIBUTE_KEY = "key";
private static final String XML_ATTRIBUTE_LAST_CONNECTION = "lastConnection";
+ private static final String SYSTEM_KEY_FILE = "/adb_keys";
/**
* Value returned by {@code getLastConnectionTime} when there is no previously saved
@@ -680,21 +825,25 @@
public static final long NO_PREVIOUS_CONNECTION = 0;
/**
- * Constructor that uses the default location for the persistent adb key store.
+ * Constructor that uses the default location for the persistent adb keystore.
*/
AdbKeyStore() {
- initKeyFile();
- mKeyMap = getKeyMapFromFile();
+ init();
}
/**
- * Constructor that uses the specified file as the location for the persistent adb key
- * store.
+ * Constructor that uses the specified file as the location for the persistent adb keystore.
*/
AdbKeyStore(File keyFile) {
mKeyFile = keyFile;
+ init();
+ }
+
+ private void init() {
initKeyFile();
- mKeyMap = getKeyMapFromFile();
+ mKeyMap = getKeyMap();
+ mSystemKeys = getSystemKeysFromFile(SYSTEM_KEY_FILE);
+ addUserKeysToKeyStore();
}
/**
@@ -710,10 +859,46 @@
}
}
+ private Set<String> getSystemKeysFromFile(String fileName) {
+ Set<String> systemKeys = new HashSet<>();
+ File systemKeyFile = new File(fileName);
+ if (systemKeyFile.exists()) {
+ try (BufferedReader in = new BufferedReader(new FileReader(systemKeyFile))) {
+ String key;
+ while ((key = in.readLine()) != null) {
+ key = key.trim();
+ if (key.length() > 0) {
+ systemKeys.add(key);
+ }
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Caught an exception reading " + fileName + ": " + e);
+ }
+ }
+ return systemKeys;
+ }
+
+ /**
+ * Returns whether there are any 'always allowed' keys in the keystore.
+ */
+ public boolean isEmpty() {
+ return mKeyMap.isEmpty();
+ }
+
+ /**
+ * Iterates through the keys in the keystore and removes any that are beyond the window
+ * within which connections are automatically allowed without user interaction.
+ */
+ public void updateKeyStore() {
+ if (filterOutOldKeys()) {
+ sendPersistKeyStoreMessage();
+ }
+ }
+
/**
* Returns the key map with the keys and last connection times from the key file.
*/
- private Map<String, Long> getKeyMapFromFile() {
+ private Map<String, Long> getKeyMap() {
Map<String, Long> keyMap = new HashMap<String, Long>();
// if the AtomicFile could not be instantiated before attempt again; if it still fails
// return an empty key map.
@@ -760,10 +945,39 @@
}
/**
+ * Updates the keystore with keys that were previously set to be always allowed before the
+ * connection time of keys was tracked.
+ */
+ private void addUserKeysToKeyStore() {
+ File userKeyFile = getUserKeyFile();
+ boolean mapUpdated = false;
+ if (userKeyFile != null && userKeyFile.exists()) {
+ try (BufferedReader in = new BufferedReader(new FileReader(userKeyFile))) {
+ long time = System.currentTimeMillis();
+ String key;
+ while ((key = in.readLine()) != null) {
+ // if the keystore does not contain the key from the user key file then add
+ // it to the Map with the current system time to prevent it from expiring
+ // immediately if the user is actively using this key.
+ if (!mKeyMap.containsKey(key)) {
+ mKeyMap.put(key, time);
+ mapUpdated = true;
+ }
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Caught an exception reading " + userKeyFile + ": " + e);
+ }
+ }
+ if (mapUpdated) {
+ sendPersistKeyStoreMessage();
+ }
+ }
+
+ /**
* Writes the key map to the key file.
*/
public void persistKeyStore() {
- // if there is nothing in the key map then ensure any keys left in the key store files
+ // if there is nothing in the key map then ensure any keys left in the keystore files
// are deleted as well.
filterOutOldKeys();
if (mKeyMap.isEmpty()) {
@@ -800,7 +1014,8 @@
}
}
- private void filterOutOldKeys() {
+ private boolean filterOutOldKeys() {
+ boolean keysDeleted = false;
long allowedTime = getAllowedConnectionTime();
long systemTime = System.currentTimeMillis();
Iterator<Map.Entry<String, Long>> keyMapIterator = mKeyMap.entrySet().iterator();
@@ -809,8 +1024,41 @@
long connectionTime = keyEntry.getValue();
if (allowedTime != 0 && systemTime > (connectionTime + allowedTime)) {
keyMapIterator.remove();
+ keysDeleted = true;
}
}
+ // if any keys were deleted then the key file should be rewritten with the active keys
+ // to prevent authorizing a key that is now beyond the allowed window.
+ if (keysDeleted) {
+ writeKeys(mKeyMap.keySet());
+ }
+ return keysDeleted;
+ }
+
+ /**
+ * Returns the time in ms that the next key will expire or -1 if there are no keys or the
+ * keys will not expire.
+ */
+ public long getNextExpirationTime() {
+ long minExpiration = -1;
+ long allowedTime = getAllowedConnectionTime();
+ // if the allowedTime is 0 then keys never expire; return -1 to indicate this
+ if (allowedTime == 0) {
+ return minExpiration;
+ }
+ long systemTime = System.currentTimeMillis();
+ Iterator<Map.Entry<String, Long>> keyMapIterator = mKeyMap.entrySet().iterator();
+ while (keyMapIterator.hasNext()) {
+ Map.Entry<String, Long> keyEntry = keyMapIterator.next();
+ long connectionTime = keyEntry.getValue();
+ // if the key has already expired then ensure that the result is set to 0 so that
+ // any scheduled jobs to clean up the keystore can run right away.
+ long keyExpiration = Math.max(0, (connectionTime + allowedTime) - systemTime);
+ if (minExpiration == -1 || keyExpiration < minExpiration) {
+ minExpiration = keyExpiration;
+ }
+ }
+ return minExpiration;
}
/**
@@ -818,6 +1066,7 @@
*/
public void deleteKeyStore() {
mKeyMap.clear();
+ deleteKeyFile();
if (mAtomicKeyFile == null) {
return;
}
@@ -836,37 +1085,31 @@
* Sets the time of the last connection for the specified key to the provided time.
*/
public void setLastConnectionTime(String key, long connectionTime) {
- // Do not set the connection time to a value that is earlier than what was previously
- // stored as the last connection time.
- if (mKeyMap.containsKey(key) && mKeyMap.get(key) >= connectionTime) {
- return;
- }
- mKeyMap.put(key, connectionTime);
- sendPersistKeyStoreMessage();
+ setLastConnectionTime(key, connectionTime, false);
}
/**
- * Returns whether the specified key should be authroized to connect without user
- * interaction. This requires that the user previously connected this device and selected
- * the option to 'Always allow', and the time since the last connection is within the
- * allowed window.
+ * Sets the time of the last connection for the specified key to the provided time. If force
+ * is set to true the time will be set even if it is older than the previously written
+ * connection time.
*/
- public boolean isKeyAuthorized(String key) {
- long lastConnectionTime = getLastConnectionTime(key);
- if (lastConnectionTime == NO_PREVIOUS_CONNECTION) {
- return false;
+ public void setLastConnectionTime(String key, long connectionTime, boolean force) {
+ // Do not set the connection time to a value that is earlier than what was previously
+ // stored as the last connection time unless force is set.
+ if (mKeyMap.containsKey(key) && mKeyMap.get(key) >= connectionTime && !force) {
+ return;
}
- long allowedConnectionTime = getAllowedConnectionTime();
- // if the allowed connection time is 0 then revert to the previous behavior of always
- // allowing previously granted adb grants.
- if (allowedConnectionTime == 0 || (System.currentTimeMillis() < (lastConnectionTime
- + allowedConnectionTime))) {
- return true;
- } else {
- // since this key is no longer auhorized remove it from the Map
- removeKey(key);
- return false;
+ // System keys are always allowed so there's no need to keep track of their connection
+ // time.
+ if (mSystemKeys.contains(key)) {
+ return;
}
+ // if this is the first time the key is being added then write it to the key file as
+ // well.
+ if (!mKeyMap.containsKey(key)) {
+ writeKey(key);
+ }
+ mKeyMap.put(key, connectionTime);
}
/**
@@ -880,14 +1123,29 @@
}
/**
- * Removes the specified key from the key store.
+ * Returns whether the specified key should be authroized to connect without user
+ * interaction. This requires that the user previously connected this device and selected
+ * the option to 'Always allow', and the time since the last connection is within the
+ * allowed window.
*/
- public void removeKey(String key) {
- if (!mKeyMap.containsKey(key)) {
- return;
+ public boolean isKeyAuthorized(String key) {
+ // A system key is always authorized to connect.
+ if (mSystemKeys.contains(key)) {
+ return true;
}
- mKeyMap.remove(key);
- sendPersistKeyStoreMessage();
+ long lastConnectionTime = getLastConnectionTime(key);
+ if (lastConnectionTime == NO_PREVIOUS_CONNECTION) {
+ return false;
+ }
+ long allowedConnectionTime = getAllowedConnectionTime();
+ // if the allowed connection time is 0 then revert to the previous behavior of always
+ // allowing previously granted adb grants.
+ if (allowedConnectionTime == 0 || (System.currentTimeMillis() < (lastConnectionTime
+ + allowedConnectionTime))) {
+ return true;
+ } else {
+ return false;
+ }
}
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index df92106..90266f1 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -634,28 +634,13 @@
}
if (allowBackgroundActivityStarts) {
- r.setHasStartedWhitelistingBgActivityStarts(true);
- scheduleCleanUpHasStartedWhitelistingBgActivityStartsLocked(r);
+ r.whitelistBgActivityStartsOnServiceStart();
}
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
- private void scheduleCleanUpHasStartedWhitelistingBgActivityStartsLocked(ServiceRecord r) {
- // if there's a request pending from the past, drop it before scheduling a new one
- if (r.startedWhitelistingBgActivityStartsCleanUp == null) {
- r.startedWhitelistingBgActivityStartsCleanUp = () -> {
- synchronized(mAm) {
- r.setHasStartedWhitelistingBgActivityStarts(false);
- }
- };
- }
- mAm.mHandler.removeCallbacks(r.startedWhitelistingBgActivityStartsCleanUp);
- mAm.mHandler.postDelayed(r.startedWhitelistingBgActivityStartsCleanUp,
- mAm.mConstants.SERVICE_BG_ACTIVITY_START_TIMEOUT);
- }
-
private boolean requestStartTargetPermissionsReviewIfNeededLocked(ServiceRecord r,
String callingPackage, int callingUid, Intent service, boolean callerFg,
final int userId) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 11ddceb..d8f5937 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -274,6 +274,7 @@
import android.os.storage.StorageManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
+import android.server.ServerProtoEnums;
import android.sysprop.VoldProperties;
import android.text.TextUtils;
import android.text.format.DateUtils;
@@ -2185,24 +2186,38 @@
"hidden_api_access_statslog_sampling_rate";
public void onPropertiesChanged(DeviceConfig.Properties properties) {
- int logSampleRate = properties.getInt(HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, 0x0);
- if (logSampleRate < 0 || logSampleRate > 0x10000) {
- logSampleRate = -1;
- }
- if (logSampleRate != -1 && logSampleRate != mLogSampleRate) {
+ int logSampleRate = properties.getInt(HIDDEN_API_ACCESS_LOG_SAMPLING_RATE,
+ mLogSampleRate);
+ int statslogSampleRate = properties.getInt(HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE,
+ mStatslogSampleRate);
+ setSampleRates(logSampleRate, statslogSampleRate);
+ }
+
+ private void setSampleRates(int logSampleRate, int statslogSampleRate) {
+ if (logSampleRate >= 0 && logSampleRate <= 0x10000
+ && logSampleRate != mLogSampleRate) {
mLogSampleRate = logSampleRate;
ZYGOTE_PROCESS.setHiddenApiAccessLogSampleRate(mLogSampleRate);
}
- int statslogSampleRate =
- properties.getInt(HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE, 0);
- if (statslogSampleRate < 0 || statslogSampleRate > 0x10000) {
- statslogSampleRate = -1;
- }
- if (statslogSampleRate != -1 && statslogSampleRate != mStatslogSampleRate) {
+ if (statslogSampleRate >= 0 && statslogSampleRate <= 0x10000
+ && statslogSampleRate != mStatslogSampleRate) {
mStatslogSampleRate = statslogSampleRate;
ZYGOTE_PROCESS.setHiddenApiAccessStatslogSampleRate(mStatslogSampleRate);
}
+
+ }
+
+ /**
+ * Set initial sampling rates from DeviceConfig. This is required after each restart,
+ * if they never get updated.
+ */
+ private void initializeSampleRates() {
+ int logSampleRate = DeviceConfig.getInt(DeviceConfig.NAMESPACE_APP_COMPAT,
+ HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, 0);
+ int statslogSampleRate = DeviceConfig.getInt(DeviceConfig.NAMESPACE_APP_COMPAT,
+ HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE, 0);
+ setSampleRates(logSampleRate, statslogSampleRate);
}
public HiddenApiSettings(Handler handler, Context context) {
@@ -2219,6 +2234,7 @@
Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY),
false,
this);
+ initializeSampleRates();
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_APP_COMPAT,
mContext.getMainExecutor(), this);
update();
@@ -9041,7 +9057,9 @@
? StatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__FOREGROUND
: StatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__BACKGROUND)
: StatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__UNKNOWN,
- (r != null) ? r.getProcessClassEnum() : 0
+ processName.equals("system_server") ? ServerProtoEnums.SYSTEM_SERVER
+ : (r != null) ? r.getProcessClassEnum()
+ : ServerProtoEnums.ERROR_SOURCE_UNKNOWN
);
final int relaunchReason = r == null ? RELAUNCH_REASON_NONE
@@ -17354,7 +17372,7 @@
@Override
public int stopUser(final int userId, boolean force, final IStopUserCallback callback) {
- return mUserController.stopUser(userId, force, callback);
+ return mUserController.stopUser(userId, force, callback, null /* keyEvictedCallback */);
}
@Override
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index ee9b561..1c2f51b 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -437,6 +437,19 @@
return next;
}
+ private void postActivityStartTokenRemoval(ProcessRecord app, BroadcastRecord r) {
+ // the receiver had run for less than allowed bg activity start timeout,
+ // so allow the process to still start activities from bg for some more time
+ String msgToken = (app.toShortString() + r.toString()).intern();
+ // first, if there exists a past scheduled request to remove this token, drop
+ // that request - we don't want the token to be swept from under our feet...
+ mHandler.removeCallbacksAndMessages(msgToken);
+ // ...then schedule the removal of the token after the extended timeout
+ mHandler.postAtTime(() -> {
+ app.removeAllowBackgroundActivityStartsToken(r);
+ }, msgToken, (r.receiverTime + mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT));
+ }
+
public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
final int state = r.state;
@@ -453,17 +466,8 @@
// just remove the token for this process now and we're done
r.curApp.removeAllowBackgroundActivityStartsToken(r);
} else {
- // the receiver had run for less than allowed bg activity start timeout,
- // so allow the process to still start activities from bg for some more time
- String msgToken = (r.curApp.toShortString() + r.toString()).intern();
- // first, if there exists a past scheduled request to remove this token, drop
- // that request - we don't want the token to be swept from under our feet...
- mHandler.removeCallbacksAndMessages(msgToken);
- // ...then schedule the removal of the token after the extended timeout
- final ProcessRecord app = r.curApp;
- mHandler.postAtTime(() -> {
- app.removeAllowBackgroundActivityStartsToken(r);
- }, msgToken, (r.receiverTime + mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT));
+ // It gets more time; post the removal to happen at the appropriate moment
+ postActivityStartTokenRemoval(r.curApp, r);
}
}
// If we're abandoning this broadcast before any receivers were actually spun up,
@@ -810,19 +814,29 @@
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
+ // parallel broadcasts are fire-and-forget, not bookended by a call to
+ // finishReceiverLocked(), so we manage their activity-start token here
+ if (r.allowBackgroundActivityStarts && !r.ordered) {
+ postActivityStartTokenRemoval(filter.receiverList.app, r);
+ }
}
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
} catch (RemoteException e) {
Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
+ // Clean up ProcessRecord state related to this broadcast attempt
+ if (filter.receiverList.app != null) {
+ filter.receiverList.app.removeAllowBackgroundActivityStartsToken(r);
+ if (ordered) {
+ filter.receiverList.app.curReceivers.remove(r);
+ }
+ }
+ // And BroadcastRecord state related to ordered delivery, if appropriate
if (ordered) {
r.receiver = null;
r.curFilter = null;
filter.receiverList.curBroadcast = null;
- if (filter.receiverList.app != null) {
- filter.receiverList.app.curReceivers.remove(r);
- }
}
}
}
@@ -1283,6 +1297,8 @@
} else {
if (filter.receiverList != null) {
maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
+ // r is guaranteed ordered at this point, so we know finishReceiverLocked()
+ // will get a callback and handle the activity start token lifecycle.
}
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(filter.owningUid,
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 7c2ea3f..30a297e 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -144,3 +144,6 @@
30064 am_on_top_resumed_gained_called (User|1|5),(Component Name|3),(Reason|3)
# The activity's onTopResumedActivityChanged(false) has been called.
30065 am_on_top_resumed_lost_called (User|1|5),(Component Name|3),(Reason|3)
+
+# An activity been add into stopping list
+30066 am_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3)
\ No newline at end of file
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index acddb47..54504c3 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -29,7 +29,6 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
-import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.TransactionTooLargeException;
@@ -388,9 +387,8 @@
userId = controller.mUserController.getCurrentOrTargetUserId();
}
// temporarily allow receivers and services to open activities from background if the
- // PendingIntent.send() caller was foreground at the time of sendInner() call, unless
- // caller is SYSTEM_UID
- final boolean allowTrampoline = uid != callingUid && callingUid != Process.SYSTEM_UID
+ // PendingIntent.send() caller was foreground at the time of sendInner() call
+ final boolean allowTrampoline = uid != callingUid
&& controller.mAtmInternal.isUidForeground(callingUid);
// note: we on purpose don't pass in the information about the PendingIntent's creator,
diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java
index 376999d..beb0e47 100644
--- a/services/core/java/com/android/server/am/PreBootBroadcaster.java
+++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java
@@ -107,9 +107,11 @@
EventLogTags.writeAmPreBoot(mUserId, componentName.getPackageName());
mIntent.setComponent(componentName);
- mService.broadcastIntentLocked(null, null, mIntent, null, this, 0, null, null, null,
- AppOpsManager.OP_NONE, null, true, false, ActivityManagerService.MY_PID,
- Process.SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), mUserId);
+ synchronized (mService) {
+ mService.broadcastIntentLocked(null, null, mIntent, null, this, 0, null, null, null,
+ AppOpsManager.OP_NONE, null, true, false, ActivityManagerService.MY_PID,
+ Process.SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), mUserId);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 32516b1..b394eea 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1658,23 +1658,15 @@
app.killed = false;
final long startSeq = app.startSeq = ++mProcStartSeqCounter;
app.setStartParams(uid, hostingRecord, seInfo, startTime);
+ app.setUsingWrapper(invokeWith != null
+ || SystemProperties.get("wrap." + app.processName) != null);
+ mPendingStarts.put(startSeq, app);
+
if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
"Posting procStart msg for " + app.toShortString());
mService.mProcStartHandler.post(() -> {
try {
- synchronized (mService) {
- final String reason = isProcStartValidLocked(app, startSeq);
- if (reason != null) {
- Slog.w(TAG_PROCESSES, app + " not valid anymore,"
- + " don't start process, " + reason);
- app.pendingStart = false;
- return;
- }
- app.setUsingWrapper(invokeWith != null
- || SystemProperties.get("wrap." + app.processName) != null);
- mPendingStarts.put(startSeq, app);
- }
final Process.ProcessStartResult startResult = startProcess(app.hostingRecord,
entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal,
app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime);
@@ -1810,11 +1802,6 @@
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
try {
- final String[] packageNames = mService.mContext.getPackageManager()
- .getPackagesForUid(uid);
- final StorageManagerInternal storageManagerInternal =
- LocalServices.getService(StorageManagerInternal.class);
- final String sandboxId = storageManagerInternal.getSandboxId(app.info.packageName);
final boolean useSystemGraphicsDriver = shouldUseSystemGraphicsDriver(mService.mContext,
mService.mCoreSettingsObserver.getCoreSettingsLocked(), app.info);
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
@@ -1826,7 +1813,6 @@
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
- packageNames, sandboxId,
useSystemGraphicsDriver,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
} else if (hostingRecord.usesAppZygote()) {
@@ -1836,15 +1822,13 @@
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
- packageNames, sandboxId, /*useUsapPool=*/ false,
- useSystemGraphicsDriver,
+ /*useUsapPool=*/ false, useSystemGraphicsDriver,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName,
- packageNames, sandboxId,
useSystemGraphicsDriver,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
}
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 0426ec1..2f1b22e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -135,7 +135,8 @@
// allowBackgroundActivityStarts=true to startServiceLocked()?
private boolean mHasStartedWhitelistingBgActivityStarts;
// used to clean up the state of hasStartedWhitelistingBgActivityStarts after a timeout
- Runnable startedWhitelistingBgActivityStartsCleanUp;
+ private Runnable mStartedWhitelistingBgActivityStartsCleanUp;
+ private ProcessRecord mAppForStartedWhitelistingBgActivityStarts;
String stringName; // caching of toString
@@ -541,14 +542,35 @@
public void setProcess(ProcessRecord _proc) {
if (_proc != null) {
+ // We're starting a new process for this service, but a previous one is whitelisted.
+ // Remove that whitelisting now (unless the new process is the same as the previous one,
+ // which is a common case).
+ if (mAppForStartedWhitelistingBgActivityStarts != null) {
+ if (mAppForStartedWhitelistingBgActivityStarts != _proc) {
+ mAppForStartedWhitelistingBgActivityStarts
+ .removeAllowBackgroundActivityStartsToken(this);
+ ams.mHandler.removeCallbacks(mStartedWhitelistingBgActivityStartsCleanUp);
+ }
+ mAppForStartedWhitelistingBgActivityStarts = null;
+ }
+ if (mHasStartedWhitelistingBgActivityStarts) {
+ // Make sure the cleanup callback knows about the new process.
+ mAppForStartedWhitelistingBgActivityStarts = _proc;
+ }
if (mHasStartedWhitelistingBgActivityStarts
|| mHasBindingWhitelistingBgActivityStarts) {
_proc.addAllowBackgroundActivityStartsToken(this);
} else {
_proc.removeAllowBackgroundActivityStartsToken(this);
}
- } else if (app != null) {
- app.removeAllowBackgroundActivityStartsToken(this);
+ }
+ if (app != null && app != _proc) {
+ // If the old app is whitelisted because of a service start, leave it whitelisted until
+ // the cleanup callback runs. Otherwise we can remove it from the whitelist immediately
+ // (it can't be bound now).
+ if (!mHasStartedWhitelistingBgActivityStarts) {
+ app.removeAllowBackgroundActivityStartsToken(this);
+ }
app.updateBoundClientUids();
}
app = _proc;
@@ -616,10 +638,7 @@
break;
}
}
- if (mHasBindingWhitelistingBgActivityStarts != hasWhitelistingBinding) {
- mHasBindingWhitelistingBgActivityStarts = hasWhitelistingBinding;
- updateParentProcessBgActivityStartsWhitelistingToken();
- }
+ setHasBindingWhitelistingBgActivityStarts(hasWhitelistingBinding);
}
void setHasBindingWhitelistingBgActivityStarts(boolean newValue) {
@@ -629,7 +648,42 @@
}
}
- void setHasStartedWhitelistingBgActivityStarts(boolean newValue) {
+ /**
+ * Called when the service is started with allowBackgroundActivityStarts set. We whitelist
+ * it for background activity starts, setting up a callback to remove the whitelisting after a
+ * timeout. Note that the whitelisting persists for the process even if the service is
+ * subsequently stopped.
+ */
+ void whitelistBgActivityStartsOnServiceStart() {
+ setHasStartedWhitelistingBgActivityStarts(true);
+
+ // This callback is stateless, so we create it once when we first need it.
+ if (mStartedWhitelistingBgActivityStartsCleanUp == null) {
+ mStartedWhitelistingBgActivityStartsCleanUp = () -> {
+ synchronized (ams) {
+ if (app == mAppForStartedWhitelistingBgActivityStarts) {
+ // The process we whitelisted is still running the service. We remove
+ // the started whitelisting, but it may still be whitelisted via bound
+ // connections.
+ setHasStartedWhitelistingBgActivityStarts(false);
+ } else if (mAppForStartedWhitelistingBgActivityStarts != null) {
+ // The process we whitelisted is not running the service. It therefore
+ // can't be bound so we can unconditionally remove the whitelist.
+ mAppForStartedWhitelistingBgActivityStarts
+ .removeAllowBackgroundActivityStartsToken(ServiceRecord.this);
+ }
+ mAppForStartedWhitelistingBgActivityStarts = null;
+ }
+ };
+ }
+
+ // if there's a request pending from the past, drop it before scheduling a new one
+ ams.mHandler.removeCallbacks(mStartedWhitelistingBgActivityStartsCleanUp);
+ ams.mHandler.postDelayed(mStartedWhitelistingBgActivityStartsCleanUp,
+ ams.mConstants.SERVICE_BG_ACTIVITY_START_TIMEOUT);
+ }
+
+ private void setHasStartedWhitelistingBgActivityStarts(boolean newValue) {
if (mHasStartedWhitelistingBgActivityStarts != newValue) {
mHasStartedWhitelistingBgActivityStarts = newValue;
updateParentProcessBgActivityStartsWhitelistingToken();
@@ -650,7 +704,7 @@
return;
}
if (mHasStartedWhitelistingBgActivityStarts || mHasBindingWhitelistingBgActivityStarts) {
- // if the token is already there it's safe to "re-add it" - we're deadling with
+ // if the token is already there it's safe to "re-add it" - we're dealing with
// a set of Binder objects
app.addAllowBackgroundActivityStartsToken(this);
} else {
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index d56cb79..21d4925 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -10,6 +10,9 @@
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
+ "exclude-annotation": "androidx.test.filters.LargeTest"
+ },
+ {
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 01a3a6f..2399d05 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -98,6 +98,7 @@
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemServiceManager;
+import com.android.server.am.UserState.KeyEvictedCallback;
import com.android.server.pm.UserManagerService;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerService;
@@ -319,7 +320,7 @@
// Owner/System user and current user can't be stopped
continue;
}
- if (stopUsersLU(userId, false, null) == USER_OP_SUCCESS) {
+ if (stopUsersLU(userId, false, null, null) == USER_OP_SUCCESS) {
iterator.remove();
}
}
@@ -586,19 +587,18 @@
}
int restartUser(final int userId, final boolean foreground) {
- return stopUser(userId, /* force */ true, new IStopUserCallback.Stub() {
+ return stopUser(userId, /* force */ true, null, new KeyEvictedCallback() {
@Override
- public void userStopped(final int userId) {
+ public void keyEvicted(@UserIdInt int userId) {
// Post to the same handler that this callback is called from to ensure the user
// cleanup is complete before restarting.
- mHandler.post(() -> startUser(userId, foreground));
+ mHandler.post(() -> UserController.this.startUser(userId, foreground));
}
- @Override
- public void userStopAborted(final int userId) {}
});
}
- int stopUser(final int userId, final boolean force, final IStopUserCallback callback) {
+ int stopUser(final int userId, final boolean force, final IStopUserCallback stopUserCallback,
+ KeyEvictedCallback keyEvictedCallback) {
if (mInjector.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: switchUser() from pid="
@@ -613,7 +613,7 @@
}
enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
synchronized (mLock) {
- return stopUsersLU(userId, force, callback);
+ return stopUsersLU(userId, force, stopUserCallback, keyEvictedCallback);
}
}
@@ -622,7 +622,8 @@
* {@link #getUsersToStopLU(int)} to determine the list of users that should be stopped.
*/
@GuardedBy("mLock")
- private int stopUsersLU(final int userId, boolean force, final IStopUserCallback callback) {
+ private int stopUsersLU(final int userId, boolean force,
+ final IStopUserCallback stopUserCallback, KeyEvictedCallback keyEvictedCallback) {
if (userId == UserHandle.USER_SYSTEM) {
return USER_OP_ERROR_IS_SYSTEM;
}
@@ -640,7 +641,7 @@
if (force) {
Slog.i(TAG,
"Force stop user " + userId + ". Related users will not be stopped");
- stopSingleUserLU(userId, callback);
+ stopSingleUserLU(userId, stopUserCallback, keyEvictedCallback);
return USER_OP_SUCCESS;
}
return USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
@@ -648,22 +649,25 @@
}
if (DEBUG_MU) Slog.i(TAG, "stopUsersLocked usersToStop=" + Arrays.toString(usersToStop));
for (int userIdToStop : usersToStop) {
- stopSingleUserLU(userIdToStop, userIdToStop == userId ? callback : null);
+ stopSingleUserLU(userIdToStop,
+ userIdToStop == userId ? stopUserCallback : null,
+ userIdToStop == userId ? keyEvictedCallback : null);
}
return USER_OP_SUCCESS;
}
@GuardedBy("mLock")
- private void stopSingleUserLU(final int userId, final IStopUserCallback callback) {
+ private void stopSingleUserLU(final int userId, final IStopUserCallback stopUserCallback,
+ KeyEvictedCallback keyEvictedCallback) {
if (DEBUG_MU) Slog.i(TAG, "stopSingleUserLocked userId=" + userId);
final UserState uss = mStartedUsers.get(userId);
if (uss == null) {
// User is not started, nothing to do... but we do need to
// callback if requested.
- if (callback != null) {
+ if (stopUserCallback != null) {
mHandler.post(() -> {
try {
- callback.userStopped(userId);
+ stopUserCallback.userStopped(userId);
} catch (RemoteException e) {
}
});
@@ -671,8 +675,11 @@
return;
}
- if (callback != null) {
- uss.mStopCallbacks.add(callback);
+ if (stopUserCallback != null) {
+ uss.mStopCallbacks.add(stopUserCallback);
+ }
+ if (keyEvictedCallback != null) {
+ uss.mKeyEvictedCallbacks.add(keyEvictedCallback);
}
if (uss.state != UserState.STATE_STOPPING
@@ -753,10 +760,12 @@
final int userId = uss.mHandle.getIdentifier();
final boolean stopped;
boolean lockUser = true;
- ArrayList<IStopUserCallback> callbacks;
+ final ArrayList<IStopUserCallback> stopCallbacks;
+ final ArrayList<KeyEvictedCallback> keyEvictedCallbacks;
int userIdToLock = userId;
synchronized (mLock) {
- callbacks = new ArrayList<>(uss.mStopCallbacks);
+ stopCallbacks = new ArrayList<>(uss.mStopCallbacks);
+ keyEvictedCallbacks = new ArrayList<>(uss.mKeyEvictedCallbacks);
if (mStartedUsers.get(userId) != uss || uss.state != UserState.STATE_SHUTDOWN) {
stopped = false;
} else {
@@ -779,11 +788,11 @@
forceStopUser(userId, "finish user");
}
- for (int i = 0; i < callbacks.size(); i++) {
+ for (final IStopUserCallback callback : stopCallbacks) {
try {
- if (stopped) callbacks.get(i).userStopped(userId);
- else callbacks.get(i).userStopAborted(userId);
- } catch (RemoteException e) {
+ if (stopped) callback.userStopped(userId);
+ else callback.userStopAborted(userId);
+ } catch (RemoteException ignored) {
}
}
@@ -814,6 +823,11 @@
} catch (RemoteException re) {
throw re.rethrowAsRuntimeException();
}
+ if (userIdToLockF == userId) {
+ for (final KeyEvictedCallback callback : keyEvictedCallbacks) {
+ callback.keyEvicted(userId);
+ }
+ }
});
}
}
@@ -912,7 +926,7 @@
if (userInfo.isGuest() || userInfo.isEphemeral()) {
// This is a user to be stopped.
synchronized (mLock) {
- stopUsersLU(oldUserId, true, null);
+ stopUsersLU(oldUserId, true, null, null);
}
}
}
@@ -1392,7 +1406,7 @@
synchronized (mLock) {
if (DEBUG_MU) Slog.i(TAG, "stopBackgroundUsersIfEnforced stopping " + oldUserId
+ " and related users");
- stopUsersLU(oldUserId, false, null);
+ stopUsersLU(oldUserId, false, null, null);
}
}
diff --git a/services/core/java/com/android/server/am/UserState.java b/services/core/java/com/android/server/am/UserState.java
index 4f5c59c..f51b3c6 100644
--- a/services/core/java/com/android/server/am/UserState.java
+++ b/services/core/java/com/android/server/am/UserState.java
@@ -19,6 +19,7 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import android.annotation.UserIdInt;
import android.app.IStopUserCallback;
import android.os.Trace;
import android.os.UserHandle;
@@ -48,15 +49,21 @@
public final static int STATE_SHUTDOWN = 5;
public final UserHandle mHandle;
- public final ArrayList<IStopUserCallback> mStopCallbacks
- = new ArrayList<IStopUserCallback>();
+ public final ArrayList<IStopUserCallback> mStopCallbacks = new ArrayList<>();
public final ProgressReporter mUnlockProgress;
+ public final ArrayList<KeyEvictedCallback> mKeyEvictedCallbacks = new ArrayList<>();
public int state = STATE_BOOTING;
public int lastState = STATE_BOOTING;
public boolean switching;
public boolean tokenProvided;
+ /** Callback for key eviction. */
+ public interface KeyEvictedCallback {
+ /** Invoked when the key is evicted. */
+ void keyEvicted(@UserIdInt int userId);
+ }
+
/**
* The last time that a provider was reported to usage stats as being brought to important
* foreground procstate.
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index c56d8ea..448e773 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -905,6 +905,8 @@
}
}
}
+
+ mHistoricalRegistry.clearHistory(uid, packageName);
}
}
@@ -3292,7 +3294,7 @@
pw.println(" Starts a given operation for a particular application.");
pw.println(" stop [--user <USER_ID>] <PACKAGE | UID> <OP> ");
pw.println(" Stops a given operation for a particular application.");
- pw.println(" set [--user <USER_ID>] <--uid PACKAGE | PACKAGE | UID> <OP> <MODE>");
+ pw.println(" set [--user <USER_ID>] <[--uid] PACKAGE | UID> <OP> <MODE>");
pw.println(" Set the mode for a particular application and operation.");
pw.println(" get [--user <USER_ID>] <PACKAGE | UID> [<OP>]");
pw.println(" Return the mode for a particular application and optional operation.");
@@ -3305,12 +3307,11 @@
pw.println(" read-settings");
pw.println(" Read the last written settings, replacing current state in RAM.");
pw.println(" options:");
- pw.println(" <PACKAGE> an Android package name.");
+ pw.println(" <PACKAGE> an Android package name or its UID if prefixed by --uid");
pw.println(" <OP> an AppOps operation.");
pw.println(" <MODE> one of allow, ignore, deny, or default");
pw.println(" <USER_ID> the user id under which the package is installed. If --user is not");
pw.println(" specified, the current user is assumed.");
- pw.println(" --uid PACKAGE refer to the UID of the package");
}
static int onShellCommand(Shell shell, String cmd) {
@@ -3560,8 +3561,6 @@
pw.println(" Limit output to data associated with the given package name.");
pw.println(" --watchers");
pw.println(" Only output the watcher sections.");
- pw.println(" --history");
- pw.println(" Output the historical data.");
}
private void dumpStatesLocked(@NonNull PrintWriter pw, @NonNull Op op,
@@ -3697,8 +3696,6 @@
}
} else if ("--watchers".equals(arg)) {
dumpWatchers = true;
- } else if ("--history".equals(arg)) {
- dumpHistory = true;
} else if (arg.length() > 0 && arg.charAt(0) == '-'){
pw.println("Unknown option: " + arg);
return;
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index d723c7b..69a1c9f5 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -472,6 +472,25 @@
DEFAULT_COMPRESSION_STEP);
}
+ void clearHistory(int uid, String packageName) {
+ synchronized (mOnDiskLock) {
+ synchronized (mInMemoryLock) {
+ if (mMode != AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
+ return;
+ }
+
+ for (int index = 0; index < mPendingWrites.size(); index++) {
+ mPendingWrites.get(index).clearHistory(uid, packageName);
+ }
+
+ getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis())
+ .clearHistory(uid, packageName);
+
+ mPersistence.clearHistoryDLocked(uid, packageName);
+ }
+ }
+ }
+
void clearHistory() {
synchronized (mOnDiskLock) {
clearHistoryOnDiskLocked();
@@ -628,6 +647,22 @@
return new File(baseDir, Long.toString(globalBeginMillis) + HISTORY_FILE_SUFFIX);
}
+ void clearHistoryDLocked(int uid, String packageName) {
+ List<HistoricalOps> historicalOps = readHistoryDLocked();
+
+ if (historicalOps == null) {
+ return;
+ }
+
+ for (int index = 0; index < historicalOps.size(); index++) {
+ historicalOps.get(index).clearHistory(uid, packageName);
+ }
+
+ clearHistoryDLocked();
+
+ persistHistoricalOpsDLocked(historicalOps);
+ }
+
void clearHistoryDLocked() {
mHistoricalAppOpsDir.delete();
}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 032af25..e148468 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -270,7 +270,7 @@
return;
}
if (!userState.mCurrentAttentionCheck.mCallbackInternal.equals(callbackInternal)) {
- Slog.e(LOG_TAG, "Cannot cancel a non-current request");
+ Slog.w(LOG_TAG, "Cannot cancel a non-current request");
return;
}
cancel(userState);
@@ -374,8 +374,15 @@
private void dumpInternal(IndentingPrintWriter ipw) {
ipw.println("Attention Manager Service (dumpsys attention) state:\n");
- ipw.printPair("context", mContext);
- ipw.println();
+ ipw.println("AttentionServicePackageName=" + getServiceConfigPackage(mContext));
+ ipw.println("Resolved component:");
+ if (mComponentName != null) {
+ ipw.increaseIndent();
+ ipw.println("Component=" + mComponentName.getPackageName());
+ ipw.println("Class=" + mComponentName.getClassName());
+ ipw.decreaseIndent();
+ }
+
synchronized (mLock) {
int size = mUserStates.size();
ipw.print("Number user states: ");
@@ -511,10 +518,24 @@
}
private void dump(IndentingPrintWriter pw) {
- pw.printPair("context", mContext);
- pw.printPair("userId", mUserId);
+ pw.println("userId=" + mUserId);
synchronized (mLock) {
- pw.printPair("binding", mBinding);
+ pw.println("binding=" + mBinding);
+ pw.println("current attention check:");
+ if (mCurrentAttentionCheck != null) {
+ pw.increaseIndent();
+ pw.println("is dispatched=" + mCurrentAttentionCheck.mIsDispatched);
+ pw.println("is fulfilled:=" + mCurrentAttentionCheck.mIsFulfilled);
+ pw.decreaseIndent();
+ }
+ pw.println("attention check cache:");
+ if (mAttentionCheckCache != null) {
+ pw.increaseIndent();
+ pw.println("last computed=" + mAttentionCheckCache.mLastComputed);
+ pw.println("timestamp=" + mAttentionCheckCache.mTimestamp);
+ pw.println("result=" + mAttentionCheckCache.mResult);
+ pw.decreaseIndent();
+ }
}
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d510912..4cde931 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -36,6 +36,8 @@
import android.app.AppOpsManager;
import android.app.IUidObserver;
import android.app.NotificationManager;
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
@@ -94,6 +96,7 @@
import android.media.audiopolicy.AudioVolumeGroup;
import android.media.audiopolicy.IAudioPolicyCallback;
import android.media.projection.IMediaProjection;
+import android.media.projection.IMediaProjectionCallback;
import android.media.projection.IMediaProjectionManager;
import android.net.Uri;
import android.os.Binder;
@@ -158,6 +161,7 @@
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
+import java.util.concurrent.Executor;
/**
* The implementation of the volume manager service.
@@ -889,9 +893,48 @@
0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
initA11yMonitoring();
+
+ mRoleObserver = new RoleObserver();
+ mRoleObserver.register();
+
onIndicateSystemReady();
}
+ RoleObserver mRoleObserver;
+
+ class RoleObserver implements OnRoleHoldersChangedListener {
+ private RoleManager mRm;
+ private final Executor mExecutor;
+
+ RoleObserver() {
+ mExecutor = mContext.getMainExecutor();
+ }
+
+ public void register() {
+ mRm = (RoleManager) mContext.getSystemService(Context.ROLE_SERVICE);
+ if (mRm != null) {
+ mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL);
+ updateAssistantUId(true);
+ }
+ }
+
+ @Override
+ public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
+ if (RoleManager.ROLE_ASSISTANT.equals(roleName)) {
+ updateAssistantUId(false);
+ }
+ }
+
+ public String getAssistantRoleHolder() {
+ String assitantPackage = "";
+ if (mRm != null) {
+ List<String> assistants = mRm.getRoleHolders(RoleManager.ROLE_ASSISTANT);
+ assitantPackage = assistants.size() == 0 ? "" : assistants.get(0);
+ }
+ return assitantPackage;
+ }
+ }
+
void onIndicateSystemReady() {
if (AudioSystem.systemReady() == AudioSystem.SUCCESS) {
return;
@@ -1391,21 +1434,33 @@
int assistantUid = 0;
// Consider assistants in the following order of priority:
- // 1) voice interaction service
- // 2) assistant
- String assistantName = Settings.Secure.getStringForUser(
- mContentResolver,
- Settings.Secure.VOICE_INTERACTION_SERVICE, UserHandle.USER_CURRENT);
- if (TextUtils.isEmpty(assistantName)) {
- assistantName = Settings.Secure.getStringForUser(
- mContentResolver,
- Settings.Secure.ASSISTANT, UserHandle.USER_CURRENT);
+ // 1) apk in assistant role
+ // 2) voice interaction service
+ // 3) assistant service
+
+ String packageName = "";
+ if (mRoleObserver != null) {
+ packageName = mRoleObserver.getAssistantRoleHolder();
}
- if (!TextUtils.isEmpty(assistantName)) {
- String packageName = ComponentName.unflattenFromString(assistantName).getPackageName();
- if (!TextUtils.isEmpty(packageName)) {
+ if (TextUtils.isEmpty(packageName)) {
+ String assistantName = Settings.Secure.getStringForUser(
+ mContentResolver,
+ Settings.Secure.VOICE_INTERACTION_SERVICE, UserHandle.USER_CURRENT);
+ if (TextUtils.isEmpty(assistantName)) {
+ assistantName = Settings.Secure.getStringForUser(
+ mContentResolver,
+ Settings.Secure.ASSISTANT, UserHandle.USER_CURRENT);
+ }
+ if (!TextUtils.isEmpty(assistantName)) {
+ packageName = ComponentName.unflattenFromString(assistantName).getPackageName();
+ }
+ }
+ if (!TextUtils.isEmpty(packageName)) {
+ PackageManager pm = mContext.getPackageManager();
+ if (pm.checkPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD, packageName)
+ == PackageManager.PERMISSION_GRANTED) {
try {
- assistantUid = mContext.getPackageManager().getPackageUid(packageName, 0);
+ assistantUid = pm.getPackageUid(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG,
"updateAssistantUId() could not find UID for package: " + packageName);
@@ -2642,7 +2697,13 @@
// The isPlatformAutomotive check is added for safety but may not be necessary.
return;
}
- if (getCurrentUserId() == userId) {
+ // For automotive,
+ // - the car service is always running as system user
+ // - foreground users are non-system users
+ // Car service is in charge of dispatching the key event include master mute to Android.
+ // Therefore, the getCurrentUser() is always different to the foreground user.
+ if ((isPlatformAutomotive() && userId == UserHandle.USER_SYSTEM)
+ || (getCurrentUserId() == userId)) {
if (mute != AudioSystem.getMasterMute()) {
setSystemAudioMute(mute);
AudioSystem.setMasterMute(mute);
@@ -4919,19 +4980,17 @@
}
private void onSetVolumeIndexOnDevice(@NonNull DeviceVolumeUpdate update) {
- synchronized (VolumeStreamState.class) {
- final VolumeStreamState streamState = mStreamStates[update.mStreamType];
- if (update.hasVolumeIndex()) {
- final int index = update.getVolumeIndex();
- streamState.setIndex(index, update.mDevice, update.mCaller);
- sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller + " dev:0x"
- + Integer.toHexString(update.mDevice) + " volIdx:" + index));
- } else {
- sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller
- + " update vol on dev:0x" + Integer.toHexString(update.mDevice)));
- }
- setDeviceVolume(streamState, update.mDevice);
+ final VolumeStreamState streamState = mStreamStates[update.mStreamType];
+ if (update.hasVolumeIndex()) {
+ final int index = update.getVolumeIndex();
+ streamState.setIndex(index, update.mDevice, update.mCaller);
+ sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller + " dev:0x"
+ + Integer.toHexString(update.mDevice) + " volIdx:" + index));
+ } else {
+ sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller
+ + " update vol on dev:0x" + Integer.toHexString(update.mDevice)));
}
+ setDeviceVolume(streamState, update.mDevice);
}
/*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) {
@@ -6651,13 +6710,13 @@
String regId = null;
synchronized (mAudioPolicies) {
+ if (mAudioPolicies.containsKey(pcb.asBinder())) {
+ Slog.e(TAG, "Cannot re-register policy");
+ return null;
+ }
try {
- if (mAudioPolicies.containsKey(pcb.asBinder())) {
- Slog.e(TAG, "Cannot re-register policy");
- return null;
- }
AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
- isFocusPolicy, isTestFocusPolicy, isVolumeController);
+ isFocusPolicy, isTestFocusPolicy, isVolumeController, projection);
pcb.asBinder().linkToDeath(app, 0/*flags*/);
regId = app.getRegistrationId();
mAudioPolicies.put(pcb.asBinder(), app);
@@ -6666,6 +6725,9 @@
Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
" binder death", e);
return null;
+ } catch (IllegalStateException e) {
+ Slog.w(TAG, "Audio policy registration failed for binder " + pcb, e);
+ return null;
}
}
return regId;
@@ -6830,9 +6892,9 @@
if (app == null){
return AudioManager.ERROR;
}
- app.addMixes(policyConfig.getMixes());
+ return app.addMixes(policyConfig.getMixes()) == AudioSystem.SUCCESS
+ ? AudioManager.SUCCESS : AudioManager.ERROR;
}
- return AudioManager.SUCCESS;
}
public int removeMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
@@ -6844,9 +6906,9 @@
if (app == null) {
return AudioManager.ERROR;
}
- app.removeMixes(policyConfig.getMixes());
+ return app.removeMixes(policyConfig.getMixes()) == AudioSystem.SUCCESS
+ ? AudioManager.SUCCESS : AudioManager.ERROR;
}
- return AudioManager.SUCCESS;
}
/** see AudioPolicy.setUidDeviceAffinity() */
@@ -7017,6 +7079,13 @@
mRecordMonitor.recorderEvent(riid, event);
}
+ /**
+ * Stop tracking the recorder
+ */
+ public void releaseRecorder(int riid) {
+ mRecordMonitor.releaseRecorder(riid);
+ }
+
public void disableRingtoneSync(final int userId) {
final int callingUserId = UserHandle.getCallingUserId();
if (callingUserId != userId) {
@@ -7104,6 +7173,15 @@
final boolean mIsVolumeController;
final HashMap<Integer, AudioDeviceArray> mUidDeviceAffinities =
new HashMap<Integer, AudioDeviceArray>();
+
+ final IMediaProjection mProjection;
+ private final class UnregisterOnStopCallback extends IMediaProjectionCallback.Stub {
+ public void onStop() {
+ unregisterAudioPolicyAsync(mPolicyCallback);
+ }
+ };
+ UnregisterOnStopCallback mProjectionCallback;
+
/**
* Audio focus ducking behavior for an audio policy.
* This variable reflects the value that was successfully set in
@@ -7117,12 +7195,13 @@
AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
boolean hasFocusListener, boolean isFocusPolicy, boolean isTestFocusPolicy,
- boolean isVolumeController) {
+ boolean isVolumeController, IMediaProjection projection) {
super(config);
setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
mPolicyCallback = token;
mHasFocusListener = hasFocusListener;
mIsVolumeController = isVolumeController;
+ mProjection = projection;
if (mHasFocusListener) {
mMediaFocusControl.addFocusFollower(mPolicyCallback);
// can only ever be true if there is a focus listener
@@ -7135,7 +7214,21 @@
if (mIsVolumeController) {
setExtVolumeController(mPolicyCallback);
}
- connectMixes();
+ if (mProjection != null) {
+ mProjectionCallback = new UnregisterOnStopCallback();
+ try {
+ mProjection.registerCallback(mProjectionCallback);
+ } catch (RemoteException e) {
+ release();
+ throw new IllegalStateException("MediaProjection callback registration failed, "
+ + "could not link to " + projection + " binder death", e);
+ }
+ }
+ int status = connectMixes();
+ if (status != AudioSystem.SUCCESS) {
+ release();
+ throw new IllegalStateException("Could not connect mix, error: " + status);
+ }
}
public void binderDied() {
@@ -7165,6 +7258,13 @@
if (mHasFocusListener) {
mMediaFocusControl.removeFocusFollower(mPolicyCallback);
}
+ if (mProjectionCallback != null) {
+ try {
+ mProjection.unregisterCallback(mProjectionCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Fail to unregister Audiopolicy callback from MediaProjection");
+ }
+ }
final long identity = Binder.clearCallingIdentity();
AudioSystem.registerPolicyMixes(mMixes, false);
Binder.restoreCallingIdentity(identity);
@@ -7199,28 +7299,29 @@
return true;
}
- void addMixes(@NonNull ArrayList<AudioMix> mixes) {
+ int addMixes(@NonNull ArrayList<AudioMix> mixes) {
// TODO optimize to not have to unregister the mixes already in place
synchronized (mMixes) {
AudioSystem.registerPolicyMixes(mMixes, false);
this.add(mixes);
- AudioSystem.registerPolicyMixes(mMixes, true);
+ return AudioSystem.registerPolicyMixes(mMixes, true);
}
}
- void removeMixes(@NonNull ArrayList<AudioMix> mixes) {
+ int removeMixes(@NonNull ArrayList<AudioMix> mixes) {
// TODO optimize to not have to unregister the mixes already in place
synchronized (mMixes) {
AudioSystem.registerPolicyMixes(mMixes, false);
this.remove(mixes);
- AudioSystem.registerPolicyMixes(mMixes, true);
+ return AudioSystem.registerPolicyMixes(mMixes, true);
}
}
- void connectMixes() {
+ int connectMixes() {
final long identity = Binder.clearCallingIdentity();
- AudioSystem.registerPolicyMixes(mMixes, true);
+ int status = AudioSystem.registerPolicyMixes(mMixes, true);
Binder.restoreCallingIdentity(identity);
+ return status;
}
int setUidDeviceAffinities(int uid, @NonNull int[] types, @NonNull String[] addresses) {
@@ -7259,6 +7360,20 @@
Log.e(TAG, "AudioSystem. removeUidDeviceAffinities failed");
return AudioManager.ERROR;
}
+
+ /** @return human readable debug informations summarizing the state of the object. */
+ public String toLogFriendlyString() {
+ String textDump = super.toLogFriendlyString();
+ textDump += " Proxy:\n";
+ textDump += " is focus policy= " + mIsFocusPolicy + "\n";
+ if (mIsFocusPolicy) {
+ textDump += " focus duck behaviour= " + mFocusDuckBehavior + "\n";
+ textDump += " is test focus policy= " + mIsTestFocusPolicy + "\n";
+ textDump += " has focus listener= " + mHasFocusListener + "\n";
+ }
+ textDump += " media projection= " + mProjection + "\n";
+ return textDump;
+ }
};
//======================
diff --git a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
index 69d1ea7..5d31dbe 100644
--- a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
@@ -176,8 +176,11 @@
dispatchCallbacks(updateSnapshot(configEvent, riid, null));
}
- void unregisterRecorder(int riid) {
- dispatchCallbacks(updateSnapshot(AudioManager.RECORD_CONFIG_EVENT_DEATH, riid, null));
+ /**
+ * Stop tracking the recorder
+ */
+ public void releaseRecorder(int riid) {
+ dispatchCallbacks(updateSnapshot(AudioManager.RECORD_CONFIG_EVENT_RELEASE, riid, null));
}
private void dispatchCallbacks(List<AudioRecordingConfiguration> configs) {
@@ -246,7 +249,7 @@
if (state.isActiveConfiguration()) {
configChanged = true;
sEventLogger.log(new RecordingEvent(
- AudioManager.RECORD_CONFIG_EVENT_DEATH,
+ AudioManager.RECORD_CONFIG_EVENT_RELEASE,
state.getRiid(), state.getConfig()));
}
it.remove();
@@ -396,7 +399,7 @@
switch (event) {
case AudioManager.RECORD_CONFIG_EVENT_START:
configChanged = state.setActive(true);
- if (config != null) { // ??? Can remove ???
+ if (config != null) {
configChanged = state.setConfig(config) || configChanged;
}
break;
@@ -412,7 +415,7 @@
mRecordStates.remove(stateIndex);
}
break;
- case AudioManager.RECORD_CONFIG_EVENT_DEATH:
+ case AudioManager.RECORD_CONFIG_EVENT_RELEASE:
configChanged = state.isActiveConfiguration();
mRecordStates.remove(stateIndex);
break;
@@ -504,7 +507,7 @@
}
public void binderDied() {
- sMonitor.unregisterRecorder(mRiid);
+ sMonitor.releaseRecorder(mRiid);
}
boolean init() {
@@ -553,8 +556,8 @@
return "update";
case AudioManager.RECORD_CONFIG_EVENT_STOP:
return "stop";
- case AudioManager.RECORD_CONFIG_EVENT_DEATH:
- return "death";
+ case AudioManager.RECORD_CONFIG_EVENT_RELEASE:
+ return "release";
default:
return "unknown (" + recEvent + ")";
}
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
index 1e0f205..b899d02 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
@@ -63,6 +63,8 @@
*/
public abstract boolean shouldFrameworkHandleLockout();
+ public abstract boolean wasUserDetected();
+
public AuthenticationClient(Context context, Constants constants,
BiometricServiceBase.DaemonWrapper daemon, long halDeviceId, IBinder token,
BiometricServiceBase.ServiceListener listener, int targetUserId, int groupId, long opId,
@@ -105,6 +107,10 @@
if (!shouldFrameworkHandleLockout()) {
switch (error) {
case BiometricConstants.BIOMETRIC_ERROR_TIMEOUT:
+ if (!wasUserDetected() && !isBiometricPrompt()) {
+ // No vibration if user was not detected on keyguard
+ break;
+ }
case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT:
case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT:
if (mStarted) {
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 6933ee8..b9a6a10 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -760,7 +760,6 @@
@Override // Binder call
public int canAuthenticate(String opPackageName) {
checkPermission();
- checkAppOp(opPackageName, Binder.getCallingUid());
final int userId = UserHandle.getCallingUserId();
final long ident = Binder.clearCallingIdentity();
@@ -833,9 +832,9 @@
}
private void checkPermission() {
- if (getContext().checkCallingPermission(USE_FINGERPRINT)
+ if (getContext().checkCallingOrSelfPermission(USE_FINGERPRINT)
!= PackageManager.PERMISSION_GRANTED) {
- getContext().enforceCallingPermission(USE_BIOMETRIC,
+ getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC,
"Must have USE_BIOMETRIC permission");
}
}
@@ -1313,6 +1312,10 @@
}
if (acquiredInfo != BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
+ if (message == null) {
+ Slog.w(TAG, "Ignoring null message: " + acquiredInfo);
+ return;
+ }
try {
mStatusBarService.onBiometricHelp(message);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/biometrics/ClientMonitor.java b/services/core/java/com/android/server/biometrics/ClientMonitor.java
index 942e050..421b3f5 100644
--- a/services/core/java/com/android/server/biometrics/ClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/ClientMonitor.java
@@ -42,7 +42,12 @@
private static final AudioAttributes FINGERPRINT_SONFICATION_ATTRIBUTES =
new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ // Temporary fix for b/123870990. No time in this release to
+ // introduce a new vibration type, but we need to distinguish these vibrations
+ // from other haptic feedback vibrations. Fortunately, Alarm vibrations have
+ // exactly the same behavior as we need
+ // TODO: refactor within the scope of b/132170758
+ .setUsage(AudioAttributes.USAGE_ALARM)
.build();
private final Context mContext;
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 37c15a0..463a499 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -64,8 +64,8 @@
import com.android.server.biometrics.AuthenticationClient;
import com.android.server.biometrics.BiometricServiceBase;
import com.android.server.biometrics.BiometricUtils;
-import com.android.server.biometrics.EnumerateClient;
import com.android.server.biometrics.Constants;
+import com.android.server.biometrics.EnumerateClient;
import com.android.server.biometrics.RemovalClient;
import org.json.JSONArray;
@@ -98,6 +98,8 @@
private static final int CHALLENGE_TIMEOUT_SEC = 600; // 10 minutes
private final class FaceAuthClient extends AuthenticationClientImpl {
+ private int mLastAcquire;
+
public FaceAuthClient(Context context,
DaemonWrapper daemon, long halDeviceId, IBinder token,
ServiceListener listener, int targetUserId, int groupId, long opId,
@@ -117,6 +119,11 @@
}
@Override
+ public boolean wasUserDetected() {
+ return mLastAcquire != FaceManager.FACE_ACQUIRED_NOT_DETECTED;
+ }
+
+ @Override
public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
final boolean result = super.onAuthenticated(identifier, authenticated, token);
@@ -153,6 +160,8 @@
@Override
public boolean onAcquired(int acquireInfo, int vendorCode) {
+ mLastAcquire = acquireInfo;
+
if (acquireInfo == FaceManager.FACE_ACQUIRED_RECALIBRATE) {
final String name =
getContext().getString(R.string.face_recalibrate_notification_name);
@@ -938,7 +947,7 @@
try {
userId = getUserOrWorkProfileId(clientPackage, userId);
if (userId != mCurrentUserId) {
- final File baseDir = Environment.getDataVendorCeDirectory(userId);
+ final File baseDir = Environment.getDataVendorDeDirectory(userId);
final File faceDir = new File(baseDir, FACE_DATA_DIR);
if (!faceDir.exists()) {
if (!faceDir.mkdir()) {
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index d91670d..24fd1b7 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -67,8 +67,8 @@
import com.android.server.biometrics.BiometricServiceBase;
import com.android.server.biometrics.BiometricUtils;
import com.android.server.biometrics.ClientMonitor;
-import com.android.server.biometrics.EnumerateClient;
import com.android.server.biometrics.Constants;
+import com.android.server.biometrics.EnumerateClient;
import com.android.server.biometrics.RemovalClient;
import org.json.JSONArray;
@@ -153,6 +153,12 @@
}
@Override
+ public boolean wasUserDetected() {
+ // TODO: Return a proper value for devices that use ERROR_TIMEOUT
+ return false;
+ }
+
+ @Override
public int handleFailedAttempt() {
final int currentUser = ActivityManager.getCurrentUser();
mFailedAttempts.put(currentUser, mFailedAttempts.get(currentUser, 0) + 1);
diff --git a/services/core/java/com/android/server/connectivity/ConnectivityConstants.java b/services/core/java/com/android/server/connectivity/ConnectivityConstants.java
index 6fa98b8..0fb6fec 100644
--- a/services/core/java/com/android/server/connectivity/ConnectivityConstants.java
+++ b/services/core/java/com/android/server/connectivity/ConnectivityConstants.java
@@ -29,7 +29,7 @@
//
// This ensures that a) the explicitly selected network is never trumped by anything else, and
// b) the explicitly selected network is never torn down.
- public static final int MAXIMUM_NETWORK_SCORE = 100;
+ public static final int EXPLICITLY_SELECTED_NETWORK_SCORE = 100;
// VPNs typically have priority over other networks. Give them a score that will
// let them win every single time.
public static final int VPN_DEFAULT_SCORE = 101;
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 35f7ea3..3de2537 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -29,6 +29,7 @@
import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
import static android.net.SocketKeepalive.ERROR_INVALID_NETWORK;
import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET;
+import static android.net.SocketKeepalive.ERROR_UNSUPPORTED;
import static android.net.SocketKeepalive.MAX_INTERVAL_SEC;
import static android.net.SocketKeepalive.MIN_INTERVAL_SEC;
import static android.net.SocketKeepalive.NO_KEEPALIVE;
@@ -46,6 +47,7 @@
import android.net.SocketKeepalive.InvalidSocketException;
import android.net.TcpKeepalivePacketData;
import android.net.util.IpUtils;
+import android.net.util.KeepaliveUtils;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -57,6 +59,7 @@
import android.util.Log;
import android.util.Pair;
+import com.android.internal.R;
import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
@@ -65,6 +68,7 @@
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
/**
@@ -90,10 +94,29 @@
@NonNull
private final Context mContext;
+ // Supported keepalive count for each transport type, can be configured through
+ // config_networkSupportedKeepaliveCount. For better error handling, use
+ // {@link getSupportedKeepalivesForNetworkCapabilities} instead of direct access.
+ @NonNull
+ private final int[] mSupportedKeepalives;
+
+ // Reserved privileged keepalive slots per transport. Caller's permission will be enforced if
+ // the number of remaining keepalive slots is less than or equal to the threshold.
+ private final int mReservedPrivilegedSlots;
+
+ // Allowed unprivileged keepalive slots per uid. Caller's permission will be enforced if
+ // the number of remaining keepalive slots is less than or equal to the threshold.
+ private final int mAllowedUnprivilegedSlotsForUid;
+
public KeepaliveTracker(Context context, Handler handler) {
mConnectivityServiceHandler = handler;
mTcpController = new TcpKeepaliveController(handler);
mContext = context;
+ mSupportedKeepalives = KeepaliveUtils.getSupportedKeepalives(mContext);
+ mReservedPrivilegedSlots = mContext.getResources().getInteger(
+ R.integer.config_reservedPrivilegedKeepaliveSlots);
+ mAllowedUnprivilegedSlotsForUid = mContext.getResources().getInteger(
+ R.integer.config_allowedUnprivilegedKeepalivePerUid);
}
/**
@@ -115,11 +138,6 @@
public static final int TYPE_NATT = 1;
public static final int TYPE_TCP = 2;
- // Max allowed unprivileged keepalive slots per network. Caller's permission will be
- // enforced if number of existing keepalives reach this limit.
- // TODO: consider making this limit configurable via resources.
- private static final int MAX_UNPRIVILEGED_SLOTS = 3;
-
// Keepalive slot. A small integer that identifies this keepalive among the ones handled
// by this network.
private int mSlot = NO_KEEPALIVE;
@@ -191,6 +209,7 @@
case NOT_STARTED : return "NOT_STARTED";
case STARTING : return "STARTING";
case STARTED : return "STARTED";
+ case STOPPING : return "STOPPING";
}
throw new IllegalArgumentException("Unknown state");
}
@@ -246,24 +265,54 @@
private int checkPermission() {
final HashMap<Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(mNai);
- int unprivilegedCount = 0;
if (networkKeepalives == null) {
return ERROR_INVALID_NETWORK;
}
- for (KeepaliveInfo ki : networkKeepalives.values()) {
- if (!ki.mPrivileged) {
- unprivilegedCount++;
- }
- if (unprivilegedCount >= MAX_UNPRIVILEGED_SLOTS) {
- return mPrivileged ? SUCCESS : ERROR_INSUFFICIENT_RESOURCES;
+
+ if (mPrivileged) return SUCCESS;
+
+ final int supported = KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(
+ mSupportedKeepalives, mNai.networkCapabilities);
+
+ int takenUnprivilegedSlots = 0;
+ for (final KeepaliveInfo ki : networkKeepalives.values()) {
+ if (!ki.mPrivileged) ++takenUnprivilegedSlots;
+ }
+ if (takenUnprivilegedSlots > supported - mReservedPrivilegedSlots) {
+ return ERROR_INSUFFICIENT_RESOURCES;
+ }
+
+ // Count unprivileged keepalives for the same uid across networks.
+ int unprivilegedCountSameUid = 0;
+ for (final HashMap<Integer, KeepaliveInfo> kaForNetwork : mKeepalives.values()) {
+ for (final KeepaliveInfo ki : kaForNetwork.values()) {
+ if (ki.mUid == mUid) {
+ unprivilegedCountSameUid++;
+ }
}
}
+ if (unprivilegedCountSameUid > mAllowedUnprivilegedSlotsForUid) {
+ return ERROR_INSUFFICIENT_RESOURCES;
+ }
+ return SUCCESS;
+ }
+
+ private int checkLimit() {
+ final HashMap<Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(mNai);
+ if (networkKeepalives == null) {
+ return ERROR_INVALID_NETWORK;
+ }
+ final int supported = KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(
+ mSupportedKeepalives, mNai.networkCapabilities);
+ if (supported == 0) return ERROR_UNSUPPORTED;
+ if (networkKeepalives.size() > supported) return ERROR_INSUFFICIENT_RESOURCES;
return SUCCESS;
}
private int isValid() {
synchronized (mNai) {
int error = checkInterval();
+ if (error == SUCCESS) error = checkLimit();
if (error == SUCCESS) error = checkPermission();
if (error == SUCCESS) error = checkNetworkConnected();
if (error == SUCCESS) error = checkSourceAddress();
@@ -278,6 +327,8 @@
Log.d(TAG, "Starting keepalive " + mSlot + " on " + mNai.name());
switch (mType) {
case TYPE_NATT:
+ mNai.asyncChannel.sendMessage(
+ CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0 /* Unused */, mPacket);
mNai.asyncChannel
.sendMessage(CMD_START_SOCKET_KEEPALIVE, slot, mInterval, mPacket);
break;
@@ -288,9 +339,8 @@
handleStopKeepalive(mNai, mSlot, ERROR_INVALID_SOCKET);
return;
}
- mNai.asyncChannel
- .sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0 /* Unused */,
- mPacket);
+ mNai.asyncChannel.sendMessage(
+ CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0 /* Unused */, mPacket);
// TODO: check result from apf and notify of failure as needed.
mNai.asyncChannel
.sendMessage(CMD_START_SOCKET_KEEPALIVE, slot, mInterval, mPacket);
@@ -314,18 +364,30 @@
Log.e(TAG, "Cannot stop unowned keepalive " + mSlot + " on " + mNai.network);
}
}
- if (NOT_STARTED != mStartedState) {
- mStartedState = STOPPING;
- Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name());
- if (mType == TYPE_NATT) {
- mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
- } else if (mType == TYPE_TCP) {
- mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
- mNai.asyncChannel.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, mSlot);
- mTcpController.stopSocketMonitor(mSlot);
- } else {
- Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
- }
+ Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name() + ": " + reason);
+ switch (mStartedState) {
+ case NOT_STARTED:
+ // Remove the reference of the keepalive that meet error before starting,
+ // e.g. invalid parameter.
+ cleanupStoppedKeepalive(mNai, mSlot);
+ break;
+ case STOPPING:
+ // Keepalive is already in stopping state, ignore.
+ return;
+ default:
+ mStartedState = STOPPING;
+ switch (mType) {
+ case TYPE_TCP:
+ mTcpController.stopSocketMonitor(mSlot);
+ // fall through
+ case TYPE_NATT:
+ mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
+ mNai.asyncChannel.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER,
+ mSlot);
+ break;
+ default:
+ Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
+ }
}
// Close the duplicated fd that maintains the lifecycle of socket whenever
@@ -400,14 +462,18 @@
}
public void handleStopAllKeepalives(NetworkAgentInfo nai, int reason) {
- HashMap <Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
+ final HashMap<Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
if (networkKeepalives != null) {
- for (KeepaliveInfo ki : networkKeepalives.values()) {
+ final ArrayList<KeepaliveInfo> kalist = new ArrayList(networkKeepalives.values());
+ for (KeepaliveInfo ki : kalist) {
ki.stop(reason);
+ // Clean up keepalives since the network agent is disconnected and unable to pass
+ // back asynchronous result of stop().
+ cleanupStoppedKeepalive(nai, ki.mSlot);
}
- networkKeepalives.clear();
- mKeepalives.remove(nai);
}
+ // Clean up keepalives will be done as a result of calling ki.stop() after the slots are
+ // freed.
}
public void handleStopKeepalive(NetworkAgentInfo nai, int slot, int reason) {
@@ -423,8 +489,24 @@
return;
}
ki.stop(reason);
+ // Clean up keepalives will be done as a result of calling ki.stop() after the slots are
+ // freed.
+ }
+
+ private void cleanupStoppedKeepalive(NetworkAgentInfo nai, int slot) {
+ String networkName = (nai == null) ? "(null)" : nai.name();
+ HashMap<Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
+ if (networkKeepalives == null) {
+ Log.e(TAG, "Attempt to remove keepalive on nonexistent network " + networkName);
+ return;
+ }
+ KeepaliveInfo ki = networkKeepalives.get(slot);
+ if (ki == null) {
+ Log.e(TAG, "Attempt to remove nonexistent keepalive " + slot + " on " + networkName);
+ return;
+ }
networkKeepalives.remove(slot);
- Log.d(TAG, "Stopped keepalive " + slot + " on " + networkName + ", "
+ Log.d(TAG, "Remove keepalive " + slot + " on " + networkName + ", "
+ networkKeepalives.size() + " remains.");
if (networkKeepalives.isEmpty()) {
mKeepalives.remove(nai);
@@ -495,10 +577,11 @@
handleStopKeepalive(nai, slot, reason);
}
} else if (KeepaliveInfo.STOPPING == ki.mStartedState) {
- // The message indicated result of stopping : don't call handleStopKeepalive.
+ // The message indicated result of stopping : clean up keepalive slots.
Log.d(TAG, "Stopped keepalive " + slot + " on " + nai.name()
+ " stopped: " + reason);
ki.mStartedState = KeepaliveInfo.NOT_STARTED;
+ cleanupStoppedKeepalive(nai, slot);
} else {
Log.wtf(TAG, "Event " + message.what + "," + slot + "," + reason
+ " for keepalive in wrong state: " + ki.toString());
@@ -642,6 +725,9 @@
}
public void dump(IndentingPrintWriter pw) {
+ pw.println("Supported Socket keepalives: " + Arrays.toString(mSupportedKeepalives));
+ pw.println("Reserved Privileged keepalives: " + mReservedPrivilegedSlots);
+ pw.println("Allowed Unprivileged keepalives per uid: " + mAllowedUnprivilegedSlotsForUid);
pw.println("Socket keepalives:");
pw.increaseIndent();
for (NetworkAgentInfo nai : mKeepalives.keySet()) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index cfa9131..34772d0 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -483,11 +483,11 @@
// down an explicitly selected network before the user gets a chance to prefer it when
// a higher-scoring network (e.g., Ethernet) is available.
if (networkMisc.explicitlySelected && (networkMisc.acceptUnvalidated || pretendValidated)) {
- return ConnectivityConstants.MAXIMUM_NETWORK_SCORE;
+ return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
}
int score = currentScore;
- if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty()) {
+ if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) {
score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY;
}
if (score < 0) score = 0;
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index ba4dcdb..998ee1e 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -1104,11 +1104,13 @@
@Override
public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
+ final int callingUid = Binder.getCallingUid();
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null && callback != null) {
- syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback);
+ syncManager.getSyncStorageEngine().addStatusChangeListener(
+ mask, UserHandle.getUserId(callingUid), callback);
}
} finally {
restoreCallingIdentity(identityToken);
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 9f80a83..d8b7c2e 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -3256,14 +3256,17 @@
}
}
- // On account add, check if there are any settings to be restored.
- for (AccountAndUser aau : mRunningAccounts) {
- if (!containsAccountAndUser(oldAccounts, aau.account, aau.userId)) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Account " + aau.account + " added, checking sync restore data");
+ if (syncTargets != null) {
+ // On account add, check if there are any settings to be restored.
+ for (AccountAndUser aau : mRunningAccounts) {
+ if (!containsAccountAndUser(oldAccounts, aau.account, aau.userId)) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Account " + aau.account
+ + " added, checking sync restore data");
+ }
+ AccountSyncSettingsBackupHelper.accountAdded(mContext, syncTargets.userId);
+ break;
}
- AccountSyncSettingsBackupHelper.accountAdded(mContext, syncTargets.userId);
- break;
}
}
@@ -3375,7 +3378,8 @@
}
scheduleSyncOperationH(op);
- mSyncStorageEngine.reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ mSyncStorageEngine.reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS,
+ target.userId);
}
/**
@@ -3877,7 +3881,8 @@
EventLog.writeEvent(2720,
syncOperation.toEventLog(SyncStorageEngine.EVENT_STOP));
mSyncStorageEngine.stopSyncEvent(rowId, elapsedTime,
- resultMessage, downstreamActivity, upstreamActivity);
+ resultMessage, downstreamActivity, upstreamActivity,
+ syncOperation.target.userId);
}
}
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 6b441a0..c7a3f4b 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -43,6 +43,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.EventLog;
import android.util.Log;
@@ -54,6 +55,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IntPair;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -588,9 +590,10 @@
return mSyncRandomOffset;
}
- public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
+ public void addStatusChangeListener(int mask, int userId, ISyncStatusObserver callback) {
synchronized (mAuthorities) {
- mChangeListeners.register(callback, mask);
+ final long cookie = IntPair.of(userId, mask);
+ mChangeListeners.register(callback, cookie);
}
}
@@ -622,14 +625,16 @@
}
}
- void reportChange(int which) {
+ void reportChange(int which, int callingUserId) {
ArrayList<ISyncStatusObserver> reports = null;
synchronized (mAuthorities) {
int i = mChangeListeners.beginBroadcast();
while (i > 0) {
i--;
- Integer mask = (Integer)mChangeListeners.getBroadcastCookie(i);
- if ((which & mask.intValue()) == 0) {
+ final long cookie = (long) mChangeListeners.getBroadcastCookie(i);
+ final int userId = IntPair.first(cookie);
+ final int mask = IntPair.second(cookie);
+ if ((which & mask) == 0 || callingUserId != userId) {
continue;
}
if (reports == null) {
@@ -719,7 +724,7 @@
new Bundle(),
syncExemptionFlag, callingUid, callingPid);
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, userId);
queueBackup();
}
@@ -787,7 +792,7 @@
requestSync(aInfo, SyncOperation.REASON_IS_SYNCABLE, new Bundle(),
ContentResolver.SYNC_EXEMPTION_NONE, callingUid, callingPid);
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, target.userId);
}
public Pair<Long, Long> getBackoff(EndPoint info) {
@@ -833,7 +838,7 @@
}
}
if (changed) {
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, info.userId);
}
}
@@ -871,7 +876,7 @@
}
public void clearAllBackoffsLocked() {
- boolean changed = false;
+ final ArraySet<Integer> changedUserIds = new ArraySet<>();
synchronized (mAuthorities) {
// Clear backoff for all sync adapters.
for (AccountInfo accountInfo : mAccounts.values()) {
@@ -888,14 +893,14 @@
}
authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
- changed = true;
+ changedUserIds.add(accountInfo.accountAndUser.userId);
}
}
}
}
- if (changed) {
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ for (int i = changedUserIds.size() - 1; i > 0; i--) {
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, changedUserIds.valueAt(i));
}
}
@@ -921,7 +926,7 @@
}
authority.delayUntil = delayUntil;
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, info.userId);
}
/**
@@ -964,7 +969,7 @@
new Bundle(),
syncExemptionFlag, callingUid, callingPid);
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, userId);
mContext.sendBroadcast(ContentResolver.ACTION_SYNC_CONN_STATUS_CHANGED);
queueBackup();
}
@@ -1015,7 +1020,7 @@
SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
status.pending = pendingValue;
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING, info.userId);
}
/**
@@ -1103,7 +1108,7 @@
activeSyncContext.mStartTime);
getCurrentSyncs(authorityInfo.target.userId).add(syncInfo);
}
- reportActiveChange();
+ reportActiveChange(activeSyncContext.mSyncOperation.target.userId);
return syncInfo;
}
@@ -1120,14 +1125,14 @@
getCurrentSyncs(userId).remove(syncInfo);
}
- reportActiveChange();
+ reportActiveChange(userId);
}
/**
* To allow others to send active change reports, to poke clients.
*/
- public void reportActiveChange() {
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
+ public void reportActiveChange(int userId) {
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE, userId);
}
/**
@@ -1162,12 +1167,12 @@
if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "returning historyId " + id);
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS, op.target.userId);
return id;
}
public void stopSyncEvent(long historyId, long elapsedTime, String resultMessage,
- long downstreamActivity, long upstreamActivity) {
+ long downstreamActivity, long upstreamActivity, int userId) {
synchronized (mAuthorities) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.v(TAG, "stopSyncEvent: historyId=" + historyId);
@@ -1307,7 +1312,7 @@
}
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS, userId);
}
/**
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 9fce644..171cc5a 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -778,6 +778,7 @@
pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
pw.println(" mUserLux=" + mUserLux);
pw.println(" mUserBrightness=" + mUserBrightness);
+ pw.println(" mDefaultConfig=" + mDefaultConfig);
}
private void computeSpline() {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 3abd0ba..6d01375 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -16,12 +16,15 @@
package com.android.server.display;
+import static android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT;
+import static android.Manifest.permission.CAPTURE_VIDEO_OUTPUT;
+import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
-import static android.hardware.display.DisplayManager
- .VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
@@ -1979,6 +1982,18 @@
}
}
+ // Sometimes users can have sensitive information in system decoration windows. An app
+ // could create a virtual display with system decorations support and read the user info
+ // from the surface.
+ // We should only allow adding flag VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+ // to virtual displays that are owned by the system.
+ if (callingUid != Process.SYSTEM_UID
+ && (flags & VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) {
+ if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "createVirtualDisplay()")) {
+ throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+ }
+ }
+
final long token = Binder.clearCallingIdentity();
try {
return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
@@ -2279,9 +2294,7 @@
Slog.e(TAG, "Unable to query projection service for permissions", e);
}
}
- if (mContext.checkCallingPermission(
- android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
- == PackageManager.PERMISSION_GRANTED) {
+ if (checkCallingPermission(CAPTURE_VIDEO_OUTPUT, "canProjectVideo()")) {
return true;
}
return canProjectSecureVideo(projection);
@@ -2297,9 +2310,17 @@
Slog.e(TAG, "Unable to query projection service for permissions", e);
}
}
- return mContext.checkCallingPermission(
- android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
- == PackageManager.PERMISSION_GRANTED;
+ return checkCallingPermission(CAPTURE_SECURE_VIDEO_OUTPUT, "canProjectSecureVideo()");
+ }
+
+ private boolean checkCallingPermission(String permission, String func) {
+ if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid() + " requires " + permission;
+ Slog.w(TAG, msg);
+ return false;
}
}
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index f599adb..ad81ca2 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -473,6 +473,20 @@
onDisplayColorModeChanged(getColorModeInternal());
}
+ private boolean isAccessiblityDaltonizerEnabled() {
+ return Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, mCurrentUser) != 0;
+ }
+
+ private boolean isAccessiblityInversionEnabled() {
+ return Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, mCurrentUser) != 0;
+ }
+
+ private boolean isAccessibilityEnabled() {
+ return isAccessiblityDaltonizerEnabled() || isAccessiblityInversionEnabled();
+ }
+
/**
* Apply the accessibility daltonizer transform based on the settings value.
*/
@@ -480,11 +494,10 @@
if (mCurrentUser == UserHandle.USER_NULL) {
return;
}
- final boolean enabled = Secure.getIntForUser(getContext().getContentResolver(),
- Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, mCurrentUser) != 0;
- final int daltonizerMode = enabled ? Secure.getIntForUser(getContext().getContentResolver(),
- Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
- AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY, mCurrentUser)
+ final int daltonizerMode = isAccessiblityDaltonizerEnabled()
+ ? Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
+ AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY, mCurrentUser)
: AccessibilityManager.DALTONIZER_DISABLED;
final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
@@ -506,11 +519,9 @@
if (mCurrentUser == UserHandle.USER_NULL) {
return;
}
- final boolean enabled = Secure.getIntForUser(getContext().getContentResolver(),
- Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, mCurrentUser) != 0;
final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_INVERT_COLOR,
- enabled ? MATRIX_INVERT_COLOR : null);
+ isAccessiblityInversionEnabled() ? MATRIX_INVERT_COLOR : null);
}
/**
@@ -598,6 +609,7 @@
boolean oldActivated = mDisplayWhiteBalanceTintController.isActivated();
mDisplayWhiteBalanceTintController.setActivated(isDisplayWhiteBalanceSettingEnabled()
&& !mNightDisplayTintController.isActivated()
+ && !isAccessibilityEnabled()
&& DisplayTransformManager.needsLinearColorMatrix());
boolean activated = mDisplayWhiteBalanceTintController.isActivated();
@@ -761,15 +773,12 @@
private @ColorMode int getColorModeInternal() {
final ContentResolver cr = getContext().getContentResolver();
- if (Secure.getIntForUser(cr, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
- 0, mCurrentUser) == 1
- || Secure.getIntForUser(cr, Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
- 0, mCurrentUser) == 1) {
+ if (isAccessibilityEnabled()) {
// There are restrictions on the available color modes combined with a11y transforms.
- if (isColorModeAvailable(COLOR_MODE_SATURATED)) {
- return COLOR_MODE_SATURATED;
- } else if (isColorModeAvailable(COLOR_MODE_AUTOMATIC)) {
- return COLOR_MODE_AUTOMATIC;
+ final int a11yColorMode = getContext().getResources().getInteger(
+ R.integer.config_accessibilityColorMode);
+ if (a11yColorMode >= 0) {
+ return a11yColorMode;
}
}
diff --git a/services/core/java/com/android/server/display/color/DisplayTransformManager.java b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
index d6aa2ba..5ff45a9 100644
--- a/services/core/java/com/android/server/display/color/DisplayTransformManager.java
+++ b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
@@ -89,12 +89,6 @@
private static final int DISPLAY_COLOR_MANAGED = 0;
private static final int DISPLAY_COLOR_UNMANAGED = 1;
private static final int DISPLAY_COLOR_ENHANCED = 2;
- /**
- * Display color mode range reserved for vendor customizations by the RenderIntent definition in
- * hardware/interfaces/graphics/common/1.1/types.hal.
- */
- private static final int VENDOR_MODE_RANGE_MIN = 256; // 0x100
- private static final int VENDOR_MODE_RANGE_MAX = 511; // 0x1ff
/**
* Map of level -> color transformation matrix.
@@ -270,7 +264,8 @@
} else if (colorMode == ColorDisplayManager.COLOR_MODE_AUTOMATIC) {
applySaturation(COLOR_SATURATION_NATURAL);
setDisplayColor(DISPLAY_COLOR_ENHANCED);
- } else if (colorMode >= VENDOR_MODE_RANGE_MIN && colorMode <= VENDOR_MODE_RANGE_MAX) {
+ } else if (colorMode >= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN
+ && colorMode <= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MAX) {
applySaturation(COLOR_SATURATION_NATURAL);
setDisplayColor(colorMode);
}
diff --git a/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java b/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
index 97c9c79..d2c6cd9 100644
--- a/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
+++ b/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
@@ -32,6 +32,7 @@
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
+import java.lang.System;
final class DisplayWhiteBalanceTintController extends TintController {
@@ -39,6 +40,7 @@
private static final int NUM_VALUES_PER_PRIMARY = 3;
// Four colors: red, green, blue, and white
private static final int NUM_DISPLAY_PRIMARIES_VALS = 4 * NUM_VALUES_PER_PRIMARY;
+ private static final int COLORSPACE_MATRIX_LENGTH = 9;
private final Object mLock = new Object();
@VisibleForTesting
@@ -46,14 +48,16 @@
@VisibleForTesting
int mTemperatureMax;
private int mTemperatureDefault;
- private float[] mDisplayNominalWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
+ @VisibleForTesting
+ float[] mDisplayNominalWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
@VisibleForTesting
ColorSpace.Rgb mDisplayColorSpaceRGB;
private float[] mChromaticAdaptationMatrix;
@VisibleForTesting
int mCurrentColorTemperature;
private float[] mCurrentColorTemperatureXYZ;
- private boolean mSetUp = false;
+ @VisibleForTesting
+ boolean mSetUp = false;
private float[] mMatrixDisplayWhiteBalance = new float[16];
private Boolean mIsAvailable;
@@ -73,6 +77,16 @@
}
}
+ // Make sure display color space is valid
+ if (!isColorMatrixValid(displayColorSpaceRGB.getTransform())) {
+ Slog.e(ColorDisplayService.TAG, "Invalid display color space RGB-to-XYZ transform");
+ return;
+ }
+ if (!isColorMatrixValid(displayColorSpaceRGB.getInverseTransform())) {
+ Slog.e(ColorDisplayService.TAG, "Invalid display color space XYZ-to-RGB transform");
+ return;
+ }
+
final String[] nominalWhiteValues = res.getStringArray(
R.array.config_displayWhiteBalanceDisplayNominalWhite);
float[] displayNominalWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
@@ -157,11 +171,16 @@
final float adaptedMaxG = result[1] + result[4] + result[7];
final float adaptedMaxB = result[2] + result[5] + result[8];
final float denum = Math.max(Math.max(adaptedMaxR, adaptedMaxG), adaptedMaxB);
- for (int i = 0; i < result.length; i++) {
- result[i] /= denum;
- }
Matrix.setIdentityM(mMatrixDisplayWhiteBalance, 0);
+ for (int i = 0; i < result.length; i++) {
+ result[i] /= denum;
+ if (!isColorMatrixCoeffValid(result[i])) {
+ Slog.e(ColorDisplayService.TAG, "Invalid DWB color matrix");
+ return;
+ }
+ }
+
java.lang.System.arraycopy(result, 0, mMatrixDisplayWhiteBalance, 0, 3);
java.lang.System.arraycopy(result, 3, mMatrixDisplayWhiteBalance, 4, 3);
java.lang.System.arraycopy(result, 6, mMatrixDisplayWhiteBalance, 8, 3);
@@ -277,4 +296,27 @@
return makeRgbColorSpaceFromXYZ(displayRedGreenBlueXYZ, displayWhiteXYZ);
}
+
+ private boolean isColorMatrixCoeffValid(float coeff) {
+ if (Float.isNaN(coeff) || Float.isInfinite(coeff)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean isColorMatrixValid(float[] matrix) {
+ if (matrix == null || matrix.length != COLORSPACE_MATRIX_LENGTH) {
+ return false;
+ }
+
+ for (int i = 0; i < matrix.length; i++) {
+ if (!isColorMatrixCoeffValid(matrix[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
}
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
index 449f115..6ff2b09 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
@@ -22,6 +22,8 @@
import android.os.Handler;
import android.util.TypedValue;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* The DisplayWhiteBalanceFactory creates and configures an DisplayWhiteBalanceController.
*/
@@ -40,7 +42,7 @@
* @param resources
* The resources used to configure the various components.
*
- * @return An DisplayWhiteBalanceController.
+ * @return A DisplayWhiteBalanceController.
*
* @throws NullPointerException
* - handler is null;
@@ -83,14 +85,23 @@
// Instantiation is disabled.
private DisplayWhiteBalanceFactory() { }
- private static AmbientSensor.AmbientBrightnessSensor createBrightnessSensor(Handler handler,
+ /**
+ * Creates a brightness sensor instance to redirect sensor data to callbacks.
+ */
+ @VisibleForTesting
+ public static AmbientSensor.AmbientBrightnessSensor createBrightnessSensor(Handler handler,
SensorManager sensorManager, Resources resources) {
final int rate = resources.getInteger(
com.android.internal.R.integer.config_displayWhiteBalanceBrightnessSensorRate);
return new AmbientSensor.AmbientBrightnessSensor(handler, sensorManager, rate);
}
- private static AmbientFilter createBrightnessFilter(Resources resources) {
+ /**
+ * Creates a BrightnessFilter which functions as a weighted moving average buffer for recent
+ * brightness values.
+ */
+ @VisibleForTesting
+ static AmbientFilter createBrightnessFilter(Resources resources) {
final int horizon = resources.getInteger(
com.android.internal.R.integer.config_displayWhiteBalanceBrightnessFilterHorizon);
final float intercept = getFloat(resources,
@@ -104,7 +115,11 @@
}
- private static AmbientSensor.AmbientColorTemperatureSensor createColorTemperatureSensor(
+ /**
+ * Creates an ambient color sensor instance to redirect sensor data to callbacks.
+ */
+ @VisibleForTesting
+ public static AmbientSensor.AmbientColorTemperatureSensor createColorTemperatureSensor(
Handler handler, SensorManager sensorManager, Resources resources) {
final String name = resources.getString(
com.android.internal.R.string
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 30d244f..6330270 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -63,7 +63,9 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.ContentObserver;
+import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManagerInternal;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
import android.os.Binder;
@@ -97,7 +99,9 @@
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.ContextThemeWrapper;
+import android.view.DisplayInfo;
import android.view.IWindowManager;
import android.view.InputChannel;
import android.view.LayoutInflater;
@@ -300,6 +304,7 @@
final SettingsObserver mSettingsObserver;
final IWindowManager mIWindowManager;
final WindowManagerInternal mWindowManagerInternal;
+ private final DisplayManagerInternal mDisplayManagerInternal;
final HandlerCaller mCaller;
final boolean mHasFeature;
private final ArrayMap<String, List<InputMethodSubtype>> mAdditionalSubtypeMap =
@@ -432,6 +437,32 @@
final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>();
+ private static final class ActivityViewInfo {
+ /**
+ * {@link ClientState} where {@link android.app.ActivityView} is running.
+ */
+ private final ClientState mParentClient;
+ /**
+ * {@link Matrix} to convert screen coordinates in the embedded virtual display to
+ * screen coordinates where {@link #mParentClient} exists.
+ */
+ private final Matrix mMatrix;
+
+ ActivityViewInfo(ClientState parentClient, Matrix matrix) {
+ mParentClient = parentClient;
+ mMatrix = matrix;
+ }
+ }
+
+ /**
+ * A mapping table from virtual display IDs created for {@link android.app.ActivityView}
+ * to its parent IME client where {@link android.app.ActivityView} is running.
+ *
+ * <p>Note: this can be used only for virtual display IDs created by
+ * {@link android.app.ActivityView}.</p>
+ */
+ private SparseArray<ActivityViewInfo> mActivityViewDisplayIdToParentMap = new SparseArray<>();
+
/**
* Set once the system is ready to run third party code.
*/
@@ -510,6 +541,16 @@
EditorInfo mCurAttribute;
/**
+ * A special {@link Matrix} to convert virtual screen coordinates to the IME target display
+ * coordinates.
+ *
+ * <p>Used only while the IME client is running in a virtual display inside
+ * {@link android.app.ActivityView}. {@code null} otherwise.</p>
+ */
+ @Nullable
+ private Matrix mCurActivityViewToScreenMatrix = null;
+
+ /**
* Id obtained with {@link InputMethodInfo#getId()} for the input method that we are currently
* connected to or in the process of connecting to.
*
@@ -1409,6 +1450,7 @@
mIWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mImeDisplayValidator = displayId -> mWindowManagerInternal.shouldShowIme(displayId);
mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() {
@Override
@@ -1883,6 +1925,15 @@
if (cs != null) {
client.asBinder().unlinkToDeath(cs.clientDeathRecipient, 0);
clearClientSessionLocked(cs);
+
+ final int numItems = mActivityViewDisplayIdToParentMap.size();
+ for (int i = numItems - 1; i >= 0; --i) {
+ final ActivityViewInfo info = mActivityViewDisplayIdToParentMap.valueAt(i);
+ if (info.mParentClient == cs) {
+ mActivityViewDisplayIdToParentMap.removeAt(i);
+ }
+ }
+
if (mCurClient == cs) {
if (mBoundToMethod) {
mBoundToMethod = false;
@@ -1892,6 +1943,7 @@
}
}
mCurClient = null;
+ mCurActivityViewToScreenMatrix = null;
}
if (mCurFocusedWindowClient == cs) {
mCurFocusedWindowClient = null;
@@ -1927,6 +1979,7 @@
MSG_UNBIND_CLIENT, mCurSeq, unbindClientReason, mCurClient.client));
mCurClient.sessionRequested = false;
mCurClient = null;
+ mCurActivityViewToScreenMatrix = null;
hideInputMethodMenuLocked();
}
@@ -1980,7 +2033,31 @@
}
return new InputBindResult(InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION,
session.session, (session.channel != null ? session.channel.dup() : null),
- mCurId, mCurSeq);
+ mCurId, mCurSeq, mCurActivityViewToScreenMatrix);
+ }
+
+ @Nullable
+ private Matrix getActivityViewToScreenMatrixLocked(int clientDisplayId, int imeDisplayId) {
+ if (clientDisplayId == imeDisplayId) {
+ return null;
+ }
+ int displayId = clientDisplayId;
+ Matrix matrix = null;
+ while (true) {
+ final ActivityViewInfo info = mActivityViewDisplayIdToParentMap.get(displayId);
+ if (info == null) {
+ return null;
+ }
+ if (matrix == null) {
+ matrix = new Matrix(info.mMatrix);
+ } else {
+ matrix.postConcat(info.mMatrix);
+ }
+ if (info.mParentClient.selfReportedDisplayId == imeDisplayId) {
+ return matrix;
+ }
+ displayId = info.mParentClient.selfReportedDisplayId;
+ }
}
@GuardedBy("mMethodMap")
@@ -1998,7 +2075,7 @@
// party code.
return new InputBindResult(
InputBindResult.ResultCode.ERROR_SYSTEM_NOT_READY,
- null, null, mCurMethodId, mCurSeq);
+ null, null, mCurMethodId, mCurSeq, null);
}
if (!InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, cs.uid,
@@ -2037,7 +2114,10 @@
if (mCurSeq <= 0) mCurSeq = 1;
mCurClient = cs;
mCurInputContext = inputContext;
- if (cs.selfReportedDisplayId != displayIdToShowIme) {
+ mCurActivityViewToScreenMatrix =
+ getActivityViewToScreenMatrixLocked(cs.selfReportedDisplayId, displayIdToShowIme);
+ if (cs.selfReportedDisplayId != displayIdToShowIme
+ && mCurActivityViewToScreenMatrix == null) {
// CursorAnchorInfo API does not work as-is for cross-display scenario. Pretend that
// InputConnection#requestCursorUpdates() is not implemented in the application so that
// IMEs will always receive false from this API.
@@ -2064,7 +2144,7 @@
requestClientSessionLocked(cs);
return new InputBindResult(
InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION,
- null, null, mCurId, mCurSeq);
+ null, null, mCurId, mCurSeq, null);
} else if (SystemClock.uptimeMillis()
< (mLastBindTime+TIME_TO_RECONNECT)) {
// In this case we have connected to the service, but
@@ -2076,7 +2156,7 @@
// to see if we can get back in touch with the service.
return new InputBindResult(
InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING,
- null, null, mCurId, mCurSeq);
+ null, null, mCurId, mCurSeq, null);
} else {
EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
@@ -2115,7 +2195,7 @@
}
return new InputBindResult(
InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING,
- null, null, mCurId, mCurSeq);
+ null, null, mCurId, mCurSeq, null);
}
mCurIntent = null;
Slog.w(TAG, "Failure connecting to input method service: " + mCurIntent);
@@ -2960,7 +3040,7 @@
}
return new InputBindResult(
InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
- null, null, null, -1);
+ null, null, null, -1, null);
}
mCurFocusedWindow = windowToken;
mCurFocusedWindowSoftInputMode = softInputMode;
@@ -3387,6 +3467,88 @@
return mWindowManagerInternal.getInputMethodWindowVisibleHeight(mCurTokenDisplayId);
}
+ @Override
+ public void reportActivityView(IInputMethodClient parentClient, int childDisplayId,
+ float[] matrixValues) {
+ final DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(childDisplayId);
+ if (displayInfo == null) {
+ throw new IllegalArgumentException(
+ "Cannot find display for non-existent displayId: " + childDisplayId);
+ }
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid != displayInfo.ownerUid) {
+ throw new SecurityException("The caller doesn't own the display.");
+ }
+
+ synchronized (mMethodMap) {
+ final ClientState cs = mClients.get(parentClient.asBinder());
+ if (cs == null) {
+ return;
+ }
+
+ // null matrixValues means that the entry needs to be removed.
+ if (matrixValues == null) {
+ final ActivityViewInfo info = mActivityViewDisplayIdToParentMap.get(childDisplayId);
+ if (info == null) {
+ return;
+ }
+ if (info.mParentClient != cs) {
+ throw new SecurityException("Only the owner client can clear"
+ + " ActivityViewGeometry for display #" + childDisplayId);
+ }
+ mActivityViewDisplayIdToParentMap.remove(childDisplayId);
+ return;
+ }
+
+ ActivityViewInfo info = mActivityViewDisplayIdToParentMap.get(childDisplayId);
+ if (info != null && info.mParentClient != cs) {
+ throw new InvalidParameterException("Display #" + childDisplayId
+ + " is already registered by " + info.mParentClient);
+ }
+ if (info == null) {
+ if (!mWindowManagerInternal.isUidAllowedOnDisplay(childDisplayId, cs.uid)) {
+ throw new SecurityException(cs + " cannot access to display #"
+ + childDisplayId);
+ }
+ info = new ActivityViewInfo(cs, new Matrix());
+ mActivityViewDisplayIdToParentMap.put(childDisplayId, info);
+ }
+ info.mMatrix.setValues(matrixValues);
+
+ if (mCurClient == null || mCurClient.curSession == null) {
+ return;
+ }
+
+ Matrix matrix = null;
+ int displayId = mCurClient.selfReportedDisplayId;
+ boolean needToNotify = false;
+ while (true) {
+ needToNotify |= (displayId == childDisplayId);
+ final ActivityViewInfo next = mActivityViewDisplayIdToParentMap.get(displayId);
+ if (next == null) {
+ break;
+ }
+ if (matrix == null) {
+ matrix = new Matrix(next.mMatrix);
+ } else {
+ matrix.postConcat(next.mMatrix);
+ }
+ if (next.mParentClient.selfReportedDisplayId == mCurTokenDisplayId) {
+ if (needToNotify) {
+ final float[] values = new float[9];
+ matrix.getValues(values);
+ try {
+ mCurClient.client.updateActivityViewToScreenMatrix(mCurSeq, values);
+ } catch (RemoteException e) {
+ }
+ }
+ break;
+ }
+ displayId = info.mParentClient.selfReportedDisplayId;
+ }
+ }
+ }
+
@BinderThread
private void notifyUserAction(@NonNull IBinder token) {
if (DEBUG) {
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index e0b8e71..3dd7304 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1619,7 +1619,7 @@
return new InputBindResult(
InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION,
null, null, data.mCurrentInputMethodInfo.getId(),
- clientInfo.mBindingSequence);
+ clientInfo.mBindingSequence, null);
case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
case InputMethodClientState.ALREADY_SENT_BIND_RESULT:
clientInfo.mBindingSequence++;
@@ -1642,7 +1642,7 @@
clientInfo.mInputMethodSession,
clientInfo.mWriteChannel.dup(),
data.mCurrentInputMethodInfo.getId(),
- clientInfo.mBindingSequence);
+ clientInfo.mBindingSequence, null);
case InputMethodClientState.UNREGISTERED:
Slog.e(TAG, "The client is already unregistered.");
return InputBindResult.INVALID_CLIENT;
@@ -1701,6 +1701,13 @@
@BinderThread
@Override
+ public void reportActivityView(IInputMethodClient parentClient, int childDisplayId,
+ float[] matrixValues) {
+ reportNotSupported();
+ }
+
+ @BinderThread
+ @Override
public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
@Nullable FileDescriptor err, String[] args, @Nullable ShellCallback callback,
ResultReceiver resultReceiver) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index b676618..35a82ae 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -49,6 +49,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ServiceInfo;
import android.database.ContentObserver;
import android.net.Uri;
@@ -1625,6 +1626,15 @@
}
/**
+ * Maximum time buffer in which JobScheduler will try to optimize periodic job scheduling. This
+ * does not cause a job's period to be larger than requested (eg: if the requested period is
+ * shorter than this buffer). This is used to put a limit on when JobScheduler will intervene
+ * and try to optimize scheduling if the current job finished less than this amount of time to
+ * the start of the next period
+ */
+ private static final long PERIODIC_JOB_WINDOW_BUFFER = 30 * MINUTE_IN_MILLIS;
+
+ /**
* Called after a periodic has executed so we can reschedule it. We take the last execution
* time of the job to be the time of completion (i.e. the time at which this function is
* called).
@@ -1644,16 +1654,18 @@
final long period = periodicToReschedule.getJob().getIntervalMillis();
final long latestRunTimeElapsed = periodicToReschedule.getOriginalLatestRunTimeElapsed();
final long flex = periodicToReschedule.getJob().getFlexMillis();
+ long rescheduleBuffer = 0;
+ final long diffMs = Math.abs(elapsedNow - latestRunTimeElapsed);
if (elapsedNow > latestRunTimeElapsed) {
// The job ran past its expected run window. Have it count towards the current window
// and schedule a new job for the next window.
if (DEBUG) {
Slog.i(TAG, "Periodic job ran after its intended window.");
}
- final long diffMs = (elapsedNow - latestRunTimeElapsed);
int numSkippedWindows = (int) (diffMs / period) + 1; // +1 to include original window
- if (period != flex && diffMs > Math.min(30 * MINUTE_IN_MILLIS, (period - flex) / 2)) {
+ if (period != flex && diffMs > Math.min(PERIODIC_JOB_WINDOW_BUFFER,
+ (period - flex) / 2)) {
if (DEBUG) {
Slog.d(TAG, "Custom flex job ran too close to next window.");
}
@@ -1664,9 +1676,15 @@
newLatestRuntimeElapsed = latestRunTimeElapsed + (period * numSkippedWindows);
} else {
newLatestRuntimeElapsed = latestRunTimeElapsed + period;
+ if (diffMs < PERIODIC_JOB_WINDOW_BUFFER && diffMs < period / 6) {
+ // Add a little buffer to the start of the next window so the job doesn't run
+ // too soon after this completed one.
+ rescheduleBuffer = Math.min(PERIODIC_JOB_WINDOW_BUFFER, period / 6 - diffMs);
+ }
}
- final long newEarliestRunTimeElapsed = newLatestRuntimeElapsed - flex;
+ final long newEarliestRunTimeElapsed = newLatestRuntimeElapsed
+ - Math.min(flex, period - rescheduleBuffer);
if (DEBUG) {
Slog.v(TAG, "Rescheduling executed periodic. New execution window [" +
@@ -2764,12 +2782,12 @@
}
@Override
- public List<JobInfo> getAllPendingJobs() throws RemoteException {
+ public ParceledListSlice<JobInfo> getAllPendingJobs() throws RemoteException {
final int uid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
try {
- return JobSchedulerService.this.getPendingJobs(uid);
+ return new ParceledListSlice<>(JobSchedulerService.this.getPendingJobs(uid));
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2905,7 +2923,7 @@
* <p class="note">This is a slow operation, so it should be called sparingly.
*/
@Override
- public List<JobSnapshot> getAllJobSnapshots() {
+ public ParceledListSlice<JobSnapshot> getAllJobSnapshots() {
final int uid = Binder.getCallingUid();
if (uid != Process.SYSTEM_UID) {
throw new SecurityException(
@@ -2916,7 +2934,7 @@
mJobs.forEachJob((job) -> snapshots.add(
new JobSnapshot(job.getJob(), job.getSatisfiedConstraintFlags(),
isReadyToBeExecutedLocked(job))));
- return snapshots;
+ return new ParceledListSlice<>(snapshots);
}
}
};
diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/GnssConfiguration.java
index 0e9ee40..aa51aec 100644
--- a/services/core/java/com/android/server/location/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/GnssConfiguration.java
@@ -70,6 +70,7 @@
private static final String CONFIG_GPS_LOCK = "GPS_LOCK";
private static final String CONFIG_ES_EXTENSION_SEC = "ES_EXTENSION_SEC";
public static final String CONFIG_NFW_PROXY_APPS = "NFW_PROXY_APPS";
+ public static final String CONFIG_ES_NOTIFY_INT = "ES_NOTIFY_INT";
// Limit on NI emergency mode time extension after emergency sessions ends
private static final int MAX_EMERGENCY_MODE_EXTENSION_SECONDS = 300; // 5 minute maximum
@@ -199,6 +200,14 @@
}
/**
+ * Returns the value of config parameter ES_NOTIFY_INT or {@code defaulEsNotify} if no
+ * value is provided or if there is an error parsing the configured value.
+ */
+ int getEsNotify(int defaulEsNotify) {
+ return getIntConfig(CONFIG_ES_NOTIFY_INT, defaulEsNotify);
+ }
+
+ /**
* Updates the GNSS HAL satellite blacklist.
*/
void setSatelliteBlacklist(int[] constellations, int[] svids) {
@@ -308,8 +317,10 @@
if (configManager == null) {
return;
}
- PersistableBundle configs = configManager.getConfigForSubId(
- SubscriptionManager.getDefaultDataSubscriptionId());
+
+ int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId();
+ PersistableBundle configs = SubscriptionManager.isValidSubscriptionId(ddSubId)
+ ? configManager.getConfigForSubId(ddSubId) : null;
if (configs == null) {
if (DEBUG) Log.d(TAG, "SIM not ready, use default carrier config.");
configs = CarrierConfigManager.getDefaultConfig();
@@ -320,10 +331,12 @@
.substring(CarrierConfigManager.Gps.KEY_PREFIX.length())
.toUpperCase();
Object value = configs.get(configKey);
+ if (DEBUG) Log.d(TAG, "Gps config: " + key + " = " + value);
if (value instanceof String) {
- // All GPS properties are of String type; convert so.
- if (DEBUG) Log.d(TAG, "Gps config: " + key + " = " + value);
+ // Most GPS properties are of String type; convert so.
mProperties.setProperty(key, (String) value);
+ } else if (value != null) {
+ mProperties.setProperty(key, value.toString());
}
}
}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index d93dddfc..b2315c7 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -60,7 +60,6 @@
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
-import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
@@ -75,6 +74,7 @@
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import com.android.internal.location.gnssmetrics.GnssMetrics;
+import com.android.internal.telephony.TelephonyIntents;
import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback;
import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
@@ -180,10 +180,10 @@
private static final int SET_REQUEST = 3;
private static final int INJECT_NTP_TIME = 5;
- private static final int DOWNLOAD_XTRA_DATA = 6;
+ // PSDS stands for Predicted Satellite Data Service
+ private static final int DOWNLOAD_PSDS_DATA = 6;
private static final int UPDATE_LOCATION = 7; // Handle external location from network listener
- private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
- private static final int SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED = 12;
+ private static final int DOWNLOAD_PSDS_DATA_FINISHED = 11;
private static final int INITIALIZE_HANDLER = 13;
private static final int REQUEST_LOCATION = 16;
private static final int REPORT_LOCATION = 17; // HAL reports location
@@ -295,34 +295,35 @@
// Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
- // how long to wait if we have a network error in NTP or XTRA downloading
+ // how long to wait if we have a network error in NTP or PSDS downloading
// the initial value of the exponential backoff
// current setting - 5 minutes
private static final long RETRY_INTERVAL = 5 * 60 * 1000;
- // how long to wait if we have a network error in NTP or XTRA downloading
+ // how long to wait if we have a network error in NTP or PSDS downloading
// the max value of the exponential backoff
// current setting - 4 hours
private static final long MAX_RETRY_INTERVAL = 4 * 60 * 60 * 1000;
- // Timeout when holding wakelocks for downloading XTRA data.
- private static final long DOWNLOAD_XTRA_DATA_TIMEOUT_MS = 60 * 1000;
+ // Timeout when holding wakelocks for downloading PSDS data.
+ private static final long DOWNLOAD_PSDS_DATA_TIMEOUT_MS = 60 * 1000;
- private final ExponentialBackOff mXtraBackOff = new ExponentialBackOff(RETRY_INTERVAL,
+ private final ExponentialBackOff mPsdsBackOff = new ExponentialBackOff(RETRY_INTERVAL,
MAX_RETRY_INTERVAL);
- // true if we are enabled, protected by this
- private boolean mEnabled;
+ // True if we are enabled
+ @GuardedBy("mLock")
+ private boolean mGpsEnabled;
private boolean mShutdown;
- // states for injecting ntp and downloading xtra data
+ // states for injecting ntp and downloading psds data
private static final int STATE_PENDING_NETWORK = 0;
private static final int STATE_DOWNLOADING = 1;
private static final int STATE_IDLE = 2;
- // 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 mDownloadXtraDataPending = STATE_PENDING_NETWORK;
+ // flags to trigger NTP or PSDS data download when network becomes available
+ // initialized to true so we do NTP and PSDS when the network comes up after booting
+ private int mDownloadPsdsDataPending = STATE_PENDING_NETWORK;
// true if GPS is navigating
private boolean mNavigating;
@@ -346,8 +347,8 @@
// capabilities reported through the top level IGnssCallback.hal
private volatile int mTopHalCapabilities;
- // true if XTRA is supported
- private boolean mSupportsXtra;
+ // true if PSDS is supported
+ private boolean mSupportsPsds;
// for calculating time to first fix
private long mFixRequestTime = 0;
@@ -404,8 +405,9 @@
// Wakelocks
private final static String WAKELOCK_KEY = "GnssLocationProvider";
private final PowerManager.WakeLock mWakeLock;
- private static final String DOWNLOAD_EXTRA_WAKELOCK_KEY = "GnssLocationProviderXtraDownload";
- private final PowerManager.WakeLock mDownloadXtraWakeLock;
+ private static final String DOWNLOAD_EXTRA_WAKELOCK_KEY = "GnssLocationProviderPsdsDownload";
+ @GuardedBy("mLock")
+ private final PowerManager.WakeLock mDownloadPsdsWakeLock;
// Alarms
private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
@@ -481,22 +483,13 @@
updateLowPowerMode();
break;
case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
+ case TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
subscriptionOrCarrierConfigChanged(context);
break;
}
}
};
- // TODO: replace OnSubscriptionsChangedListener with ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED
- // broadcast receiver.
- private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
- new OnSubscriptionsChangedListener() {
- @Override
- public void onSubscriptionsChanged() {
- sendMessage(SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED, 0, null);
- }
- };
-
/**
* Implements {@link GnssSatelliteBlacklistCallback#onUpdateSatelliteBlacklist}.
*/
@@ -512,33 +505,33 @@
mContext.getSystemService(Context.TELEPHONY_SERVICE);
CarrierConfigManager configManager = (CarrierConfigManager)
mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
- String mccMnc = phone.getSimOperator();
+ int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId();
+ String mccMnc = SubscriptionManager.isValidSubscriptionId(ddSubId)
+ ? phone.getSimOperator(ddSubId) : phone.getSimOperator();
boolean isKeepLppProfile = false;
if (!TextUtils.isEmpty(mccMnc)) {
if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
- synchronized (mLock) {
- if (configManager != null) {
- PersistableBundle b = configManager.getConfig();
- if (b != null) {
- isKeepLppProfile =
- b.getBoolean(CarrierConfigManager.Gps.KEY_PERSIST_LPP_MODE_BOOL);
- }
+ if (configManager != null) {
+ PersistableBundle b = SubscriptionManager.isValidSubscriptionId(ddSubId)
+ ? configManager.getConfigForSubId(ddSubId) : null;
+ if (b != null) {
+ isKeepLppProfile =
+ b.getBoolean(CarrierConfigManager.Gps.KEY_PERSIST_LPP_MODE_BOOL);
}
- if (isKeepLppProfile) {
- // load current properties for the carrier
- mGnssConfiguration.loadPropertiesFromCarrierConfig();
- String lpp_profile = mGnssConfiguration.getLppProfile();
- // set the persist property LPP_PROFILE for the value
- if (lpp_profile != null) {
- SystemProperties.set(GnssConfiguration.LPP_PROFILE, lpp_profile);
- }
- } else {
- // reset the persist property
- SystemProperties.set(GnssConfiguration.LPP_PROFILE, "");
- }
- reloadGpsProperties();
- mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
}
+ if (isKeepLppProfile) {
+ // load current properties for the carrier
+ mGnssConfiguration.loadPropertiesFromCarrierConfig();
+ String lpp_profile = mGnssConfiguration.getLppProfile();
+ // set the persist property LPP_PROFILE for the value
+ if (lpp_profile != null) {
+ SystemProperties.set(GnssConfiguration.LPP_PROFILE, lpp_profile);
+ }
+ } else {
+ // reset the persist property
+ SystemProperties.set(GnssConfiguration.LPP_PROFILE, "");
+ }
+ reloadGpsProperties();
} else {
if (DEBUG) Log.d(TAG, "SIM MCC/MNC is still not available");
}
@@ -576,8 +569,9 @@
mC2KServerPort = mGnssConfiguration.getC2KPort(TCP_MIN_PORT);
mNIHandler.setEmergencyExtensionSeconds(mGnssConfiguration.getEsExtensionSec());
mSuplEsEnabled = mGnssConfiguration.getSuplEs(0) == 1;
+ mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
if (mGnssVisibilityControl != null) {
- mGnssVisibilityControl.updateProxyApps(mGnssConfiguration.getProxyApps());
+ mGnssVisibilityControl.onConfigurationUpdated(mGnssConfiguration);
}
}
@@ -592,10 +586,10 @@
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
mWakeLock.setReferenceCounted(true);
- // Create a separate wake lock for xtra downloader as it may be released due to timeout.
- mDownloadXtraWakeLock = mPowerManager.newWakeLock(
+ // Create a separate wake lock for psds downloader as it may be released due to timeout.
+ mDownloadPsdsWakeLock = mPowerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, DOWNLOAD_EXTRA_WAKELOCK_KEY);
- mDownloadXtraWakeLock.setReferenceCounted(true);
+ mDownloadPsdsWakeLock.setReferenceCounted(true);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
@@ -635,14 +629,14 @@
@Override
protected boolean isGpsEnabled() {
- return isEnabled();
+ return GnssLocationProvider.this.isGpsEnabled();
}
};
mGnssMeasurementsProvider = new GnssMeasurementsProvider(mContext, mHandler) {
@Override
protected boolean isGpsEnabled() {
- return isEnabled();
+ return GnssLocationProvider.this.isGpsEnabled();
}
};
@@ -651,7 +645,7 @@
mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mContext, mHandler) {
@Override
protected boolean isGpsEnabled() {
- return isEnabled();
+ return GnssLocationProvider.this.isGpsEnabled();
}
};
@@ -701,10 +695,10 @@
*/
private void onNetworkAvailable() {
mNtpTimeHelper.onNetworkAvailable();
- if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
- if (mSupportsXtra) {
+ if (mDownloadPsdsDataPending == STATE_PENDING_NETWORK) {
+ if (mSupportsPsds) {
// Download only if supported, (prevents an unnecessary on-boot download)
- xtraDownloadRequest();
+ psdsDownloadRequest();
}
}
}
@@ -811,61 +805,63 @@
return false;
}
- private void handleDownloadXtraData() {
- if (!mSupportsXtra) {
- // native code reports xtra not supported, don't try
- Log.d(TAG, "handleDownloadXtraData() called when Xtra not supported");
+ private void handleDownloadPsdsData() {
+ if (!mSupportsPsds) {
+ // native code reports psds not supported, don't try
+ Log.d(TAG, "handleDownloadPsdsData() called when PSDS not supported");
return;
}
- if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
+ if (mDownloadPsdsDataPending == STATE_DOWNLOADING) {
// already downloading data
return;
}
if (!mNetworkConnectivityHandler.isDataNetworkConnected()) {
// try again when network is up
- mDownloadXtraDataPending = STATE_PENDING_NETWORK;
+ mDownloadPsdsDataPending = STATE_PENDING_NETWORK;
return;
}
- mDownloadXtraDataPending = STATE_DOWNLOADING;
+ mDownloadPsdsDataPending = STATE_DOWNLOADING;
- // hold wake lock while task runs
- mDownloadXtraWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS);
- Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()");
+ synchronized (mLock) {
+ // hold wake lock while task runs
+ mDownloadPsdsWakeLock.acquire(DOWNLOAD_PSDS_DATA_TIMEOUT_MS);
+ }
+ Log.i(TAG, "WakeLock acquired by handleDownloadPsdsData()");
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
- GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(
+ GpsPsdsDownloader psdsDownloader = new GpsPsdsDownloader(
mGnssConfiguration.getProperties());
- byte[] data = xtraDownloader.downloadXtraData();
+ byte[] data = psdsDownloader.downloadPsdsData();
if (data != null) {
- if (DEBUG) Log.d(TAG, "calling native_inject_xtra_data");
- native_inject_xtra_data(data, data.length);
- mXtraBackOff.reset();
+ if (DEBUG) Log.d(TAG, "calling native_inject_psds_data");
+ native_inject_psds_data(data, data.length);
+ mPsdsBackOff.reset();
}
- sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
+ sendMessage(DOWNLOAD_PSDS_DATA_FINISHED, 0, null);
if (data == null) {
// try again later
// since this is delayed and not urgent we do not hold a wake lock here
- mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA,
- mXtraBackOff.nextBackoffMillis());
+ mHandler.sendEmptyMessageDelayed(DOWNLOAD_PSDS_DATA,
+ mPsdsBackOff.nextBackoffMillis());
}
// Release wake lock held by task, synchronize on mLock in case multiple
// download tasks overrun.
synchronized (mLock) {
- if (mDownloadXtraWakeLock.isHeld()) {
+ if (mDownloadPsdsWakeLock.isHeld()) {
// This wakelock may have time-out, if a timeout was specified.
// Catch (and ignore) any timeout exceptions.
try {
- mDownloadXtraWakeLock.release();
- if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadXtraData()");
+ mDownloadPsdsWakeLock.release();
+ if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadPsdsData()");
} catch (Exception e) {
Log.i(TAG, "Wakelock timeout & release race exception in "
- + "handleDownloadXtraData()", e);
+ + "handleDownloadPsdsData()", e);
}
} else {
Log.e(TAG, "WakeLock expired before release in "
- + "handleDownloadXtraData()");
+ + "handleDownloadPsdsData()");
}
}
});
@@ -912,15 +908,20 @@
return GPS_POSITION_MODE_STANDALONE;
}
- @GuardedBy("mLock")
- private void handleEnableLocked() {
- if (DEBUG) Log.d(TAG, "handleEnableLocked");
+ private void setGpsEnabled(boolean enabled) {
+ synchronized (mLock) {
+ mGpsEnabled = enabled;
+ }
+ }
+
+ private void handleEnable() {
+ if (DEBUG) Log.d(TAG, "handleEnable");
boolean inited = native_init();
if (inited) {
- mEnabled = true;
- mSupportsXtra = native_supports_xtra();
+ setGpsEnabled(true);
+ mSupportsPsds = native_supports_psds();
// TODO: remove the following native calls if we can make sure they are redundant.
if (mSuplServerHost != null) {
@@ -936,26 +937,25 @@
mGnssNavigationMessageProvider.onGpsEnabledChanged();
mGnssBatchingProvider.enable();
if (mGnssVisibilityControl != null) {
- mGnssVisibilityControl.onGpsEnabledChanged(mEnabled);
+ mGnssVisibilityControl.onGpsEnabledChanged(/* isEnabled= */true);
}
} else {
- mEnabled = false;
+ setGpsEnabled(false);
Log.w(TAG, "Failed to enable location provider");
}
}
- @GuardedBy("mLock")
- private void handleDisableLocked() {
- if (DEBUG) Log.d(TAG, "handleDisableLocked");
+ private void handleDisable() {
+ if (DEBUG) Log.d(TAG, "handleDisable");
- mEnabled = false;
+ setGpsEnabled(false);
updateClientUids(new WorkSource());
stopNavigating();
mAlarmManager.cancel(mWakeupIntent);
mAlarmManager.cancel(mTimeoutIntent);
if (mGnssVisibilityControl != null) {
- mGnssVisibilityControl.onGpsEnabledChanged(mEnabled);
+ mGnssVisibilityControl.onGpsEnabledChanged(/* isEnabled= */ false);
}
mGnssBatchingProvider.disable();
// do this before releasing wakelock
@@ -966,35 +966,33 @@
}
private void updateEnabled() {
- synchronized (mLock) {
- // Generally follow location setting
- boolean enabled = mContext.getSystemService(LocationManager.class).isLocationEnabled();
+ // Generally follow location setting
+ boolean enabled = mContext.getSystemService(LocationManager.class).isLocationEnabled();
- // ... but disable if PowerManager overrides
- enabled &= !mDisableGpsForPowerManager;
+ // ... but disable if PowerManager overrides
+ enabled &= !mDisableGpsForPowerManager;
- // .. but enable anyway, if there's an active settings-ignored request (e.g. ELS)
- enabled |= (mProviderRequest != null && mProviderRequest.reportLocation
- && mProviderRequest.locationSettingsIgnored);
+ // .. but enable anyway, if there's an active settings-ignored request (e.g. ELS)
+ enabled |= (mProviderRequest != null && mProviderRequest.reportLocation
+ && mProviderRequest.locationSettingsIgnored);
- // ... and, finally, disable anyway, if device is being shut down
- enabled &= !mShutdown;
+ // ... and, finally, disable anyway, if device is being shut down
+ enabled &= !mShutdown;
- if (enabled == mEnabled) {
- return;
- }
+ if (enabled == isGpsEnabled()) {
+ return;
+ }
- if (enabled) {
- handleEnableLocked();
- } else {
- handleDisableLocked();
- }
+ if (enabled) {
+ handleEnable();
+ } else {
+ handleDisable();
}
}
- public boolean isEnabled() {
+ private boolean isGpsEnabled() {
synchronized (mLock) {
- return mEnabled;
+ return mGpsEnabled;
}
}
@@ -1035,7 +1033,7 @@
}
if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
- if (mProviderRequest.reportLocation && isEnabled()) {
+ if (mProviderRequest.reportLocation && isGpsEnabled()) {
// update client uids
updateClientUids(mWorkSource);
@@ -1162,9 +1160,9 @@
deleteAidingData(extras);
} else if ("force_time_injection".equals(command)) {
requestUtcTime();
- } else if ("force_xtra_injection".equals(command)) {
- if (mSupportsXtra) {
- xtraDownloadRequest();
+ } else if ("force_psds_injection".equals(command)) {
+ if (mSupportsPsds) {
+ psdsDownloadRequest();
}
} else {
Log.w(TAG, "sendExtraCommand: unknown command " + command);
@@ -1596,12 +1594,10 @@
private void reportGnssServiceDied() {
if (DEBUG) Log.d(TAG, "reportGnssServiceDied");
mHandler.post(() -> {
- class_init_native();
- native_init_once();
- if (isEnabled()) {
- synchronized (mLock) {
- mEnabled = false;
- }
+ setupNativeGnssService(/* reinitializeGnssServiceHandle = */ true);
+ if (isGpsEnabled()) {
+ setGpsEnabled(false);
+
updateEnabled();
// resend configuration into the restarted HAL service.
@@ -1677,9 +1673,9 @@
}
@NativeEntryPoint
- private void xtraDownloadRequest() {
- if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
- sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
+ private void psdsDownloadRequest() {
+ if (DEBUG) Log.d(TAG, "psdsDownloadRequest");
+ sendMessage(DOWNLOAD_PSDS_DATA, 0, null);
}
/**
@@ -1809,7 +1805,7 @@
/* requestorIdEncoding= */ 0,
/* textEncoding= */ 0,
mSuplEsEnabled,
- isEnabled(),
+ isGpsEnabled(),
userResponse);
return true;
@@ -1875,7 +1871,7 @@
notification.requestorIdEncoding,
notification.textEncoding,
mSuplEsEnabled,
- isEnabled(),
+ isGpsEnabled(),
/* userResponse= */ 0);
}
@@ -1888,28 +1884,34 @@
TelephonyManager phone = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
int type = AGPS_SETID_TYPE_NONE;
- String data = "";
+ String setId = null;
+ int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId();
if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
- String data_temp = phone.getSubscriberId();
- if (data_temp == null) {
- // This means the framework does not have the SIM card ready.
- } else {
+ if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
+ setId = phone.getSubscriberId(ddSubId);
+ }
+ if (setId == null) {
+ setId = phone.getSubscriberId();
+ }
+ if (setId != null) {
// This means the framework has the SIM card.
- data = data_temp;
type = AGPS_SETID_TYPE_IMSI;
}
} else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
- String data_temp = phone.getLine1Number();
- if (data_temp == null) {
- // This means the framework does not have the SIM card ready.
- } else {
+ if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
+ setId = phone.getLine1Number(ddSubId);
+ }
+ if (setId == null) {
+ setId = phone.getLine1Number();
+ }
+ if (setId != null) {
// This means the framework has the SIM card.
- data = data_temp;
type = AGPS_SETID_TYPE_MSISDN;
}
}
- native_agps_set_id(type, data);
+
+ native_agps_set_id(type, (setId == null) ? "" : setId);
}
@NativeEntryPoint
@@ -2012,18 +2014,15 @@
case REQUEST_LOCATION:
handleRequestLocation(msg.arg1 == 1, (boolean) msg.obj);
break;
- case DOWNLOAD_XTRA_DATA:
- handleDownloadXtraData();
+ case DOWNLOAD_PSDS_DATA:
+ handleDownloadPsdsData();
break;
- case DOWNLOAD_XTRA_DATA_FINISHED:
- mDownloadXtraDataPending = STATE_IDLE;
+ case DOWNLOAD_PSDS_DATA_FINISHED:
+ mDownloadPsdsDataPending = STATE_IDLE;
break;
case UPDATE_LOCATION:
handleUpdateLocation((Location) msg.obj);
break;
- case SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED:
- subscriptionOrCarrierConfigChanged(mContext);
- break;
case INITIALIZE_HANDLER:
handleInitialize();
break;
@@ -2051,40 +2050,17 @@
* this handler.
*/
private void handleInitialize() {
- native_init_once();
-
- /*
- * A cycle of native_init() and native_cleanup() is needed so that callbacks are
- * registered after bootup even when location is disabled.
- * This will allow Emergency SUPL to work even when location is disabled before device
- * restart.
- */
- boolean isInitialized = native_init();
- if (!isInitialized) {
- Log.w(TAG, "Native initialization failed at bootup");
- } else {
- native_cleanup();
- }
+ // class_init_native() already initializes the GNSS service handle during class loading.
+ setupNativeGnssService(/* reinitializeGnssServiceHandle = */ false);
if (native_is_gnss_visibility_control_supported()) {
- mGnssVisibilityControl = new GnssVisibilityControl(mContext, mLooper);
+ mGnssVisibilityControl = new GnssVisibilityControl(mContext, mLooper, mNIHandler);
}
// load default GPS configuration
// (this configuration might change in the future based on SIM changes)
reloadGpsProperties();
- // TODO: When this object "finishes" we should unregister by invoking
- // SubscriptionManager.getInstance(mContext).unregister
- // (mOnSubscriptionsChangedListener);
- // This is not strictly necessary because it will be unregistered if the
- // notification fails but it is good form.
-
- // Register for SubscriptionInfo list changes which is guaranteed
- // to invoke onSubscriptionsChanged the first time.
- SubscriptionManager.from(mContext)
- .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
-
// listen for events
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ALARM_WAKEUP);
@@ -2094,6 +2070,7 @@
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ intentFilter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
mNetworkConnectivityHandler.registerNetworkCallbacks();
@@ -2166,14 +2143,12 @@
return "INJECT_NTP_TIME";
case REQUEST_LOCATION:
return "REQUEST_LOCATION";
- case DOWNLOAD_XTRA_DATA:
- return "DOWNLOAD_XTRA_DATA";
- case DOWNLOAD_XTRA_DATA_FINISHED:
- return "DOWNLOAD_XTRA_DATA_FINISHED";
+ case DOWNLOAD_PSDS_DATA:
+ return "DOWNLOAD_PSDS_DATA";
+ case DOWNLOAD_PSDS_DATA_FINISHED:
+ return "DOWNLOAD_PSDS_DATA_FINISHED";
case UPDATE_LOCATION:
return "UPDATE_LOCATION";
- case SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED:
- return "SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED";
case INITIALIZE_HANDLER:
return "INITIALIZE_HANDLER";
case REPORT_LOCATION:
@@ -2226,6 +2201,23 @@
pw.append(s);
}
+ private void setupNativeGnssService(boolean reinitializeGnssServiceHandle) {
+ native_init_once(reinitializeGnssServiceHandle);
+
+ /*
+ * A cycle of native_init() and native_cleanup() is needed so that callbacks are
+ * registered after bootup even when location is disabled.
+ * This will allow Emergency SUPL to work even when location is disabled before device
+ * restart.
+ */
+ boolean isInitialized = native_init();
+ if (!isInitialized) {
+ Log.w(TAG, "Native initialization failed.");
+ } else {
+ native_cleanup();
+ }
+ }
+
// preallocated to avoid memory allocation in reportNmea()
private byte[] mNmeaBuffer = new byte[120];
@@ -2239,7 +2231,7 @@
private static native boolean native_is_gnss_visibility_control_supported();
- private static native void native_init_once();
+ private static native void native_init_once(boolean reinitializeGnssServiceHandle);
private native boolean native_init();
@@ -2266,12 +2258,12 @@
private native void native_inject_location(double latitude, double longitude, float accuracy);
- // XTRA Support
+ // PSDS Support
private native void native_inject_time(long time, long timeReference, int uncertainty);
- private native boolean native_supports_xtra();
+ private native boolean native_supports_psds();
- private native void native_inject_xtra_data(byte[] data, int length);
+ private native void native_inject_psds_data(byte[] data, int length);
// DEBUG Support
private native String native_get_internal_state();
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
index 8391f9d..c49d900 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
@@ -32,6 +33,9 @@
import android.util.Log;
import android.util.StatsLog;
+import com.android.internal.R;
+import com.android.internal.location.GpsNetInitiatedHandler;
+
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -54,6 +58,11 @@
// Max wait time for synchronous method onGpsEnabledChanged() to run.
private static final long ON_GPS_ENABLED_CHANGED_TIMEOUT_MILLIS = 3 * 1000;
+ // Valid values for config parameter es_notify_int for posting notification in the status
+ // bar for non-framework location requests in user-initiated emergency use cases.
+ private static final int ES_NOTIFY_NONE = 0;
+ private static final int ES_NOTIFY_ALL = 1;
+
// Wakelocks
private static final String WAKELOCK_KEY = TAG;
private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
@@ -64,8 +73,10 @@
private final Handler mHandler;
private final Context mContext;
+ private final GpsNetInitiatedHandler mNiHandler;
private boolean mIsGpsEnabled;
+ private boolean mEsNotify;
// Number of non-framework location access proxy apps is expected to be small (< 5).
private static final int ARRAY_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS = 7;
@@ -75,11 +86,12 @@
private PackageManager.OnPermissionsChangedListener mOnPermissionsChangedListener =
uid -> runOnHandler(() -> handlePermissionsChanged(uid));
- GnssVisibilityControl(Context context, Looper looper) {
+ GnssVisibilityControl(Context context, Looper looper, GpsNetInitiatedHandler niHandler) {
mContext = context;
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
mHandler = new Handler(looper);
+ mNiHandler = niHandler;
mAppOps = mContext.getSystemService(AppOpsManager.class);
mPackageManager = mContext.getPackageManager();
@@ -112,10 +124,6 @@
}
}
- void updateProxyApps(List<String> nfwLocationAccessProxyApps) {
- runOnHandler(() -> handleUpdateProxyApps(nfwLocationAccessProxyApps));
- }
-
void reportNfwNotification(String proxyAppPackageName, byte protocolStack,
String otherProtocolStackName, byte requestor, String requestorId, byte responseType,
boolean inEmergencyMode, boolean isCachedLocation) {
@@ -124,6 +132,27 @@
requestor, requestorId, responseType, inEmergencyMode, isCachedLocation)));
}
+ void onConfigurationUpdated(GnssConfiguration configuration) {
+ // The configuration object must be accessed only in the caller thread and not in mHandler.
+ List<String> nfwLocationAccessProxyApps = configuration.getProxyApps();
+ int esNotify = configuration.getEsNotify(ES_NOTIFY_NONE);
+ runOnHandler(() -> {
+ setEsNotify(esNotify);
+ handleUpdateProxyApps(nfwLocationAccessProxyApps);
+ });
+ }
+
+ private void setEsNotify(int esNotify) {
+ if (esNotify != ES_NOTIFY_NONE && esNotify != ES_NOTIFY_ALL) {
+ Log.e(TAG, "Config parameter " + GnssConfiguration.CONFIG_ES_NOTIFY_INT
+ + " is set to invalid value: " + esNotify
+ + ". Using default value: " + ES_NOTIFY_NONE);
+ esNotify = ES_NOTIFY_NONE;
+ }
+
+ mEsNotify = (esNotify == ES_NOTIFY_ALL);
+ }
+
private void handleInitialize() {
disableNfwLocationAccess(); // Disable until config properties are loaded.
listenForProxyAppsPackageUpdates();
@@ -135,6 +164,7 @@
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+ intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
intentFilter.addDataScheme("package");
mContext.registerReceiverAsUser(new BroadcastReceiver() {
@Override
@@ -148,6 +178,7 @@
case Intent.ACTION_PACKAGE_ADDED:
case Intent.ACTION_PACKAGE_REMOVED:
case Intent.ACTION_PACKAGE_REPLACED:
+ case Intent.ACTION_PACKAGE_CHANGED:
String pkgName = intent.getData().getEncodedSchemeSpecificPart();
handleProxyAppPackageUpdate(pkgName, action);
break;
@@ -162,10 +193,12 @@
return; // ignore, pkgName is not one of the proxy apps in our list.
}
- Log.i(TAG, "Proxy app " + pkgName + " package changed: " + action);
- final boolean updatedLocationPermission = hasLocationPermission(pkgName);
+ if (DEBUG) Log.d(TAG, "Proxy app " + pkgName + " package changed: " + action);
+ final boolean updatedLocationPermission = shouldEnableLocationPermissionInGnssHal(pkgName);
if (locationPermission != updatedLocationPermission) {
// Permission changed. So, update the GNSS HAL with the updated list.
+ Log.i(TAG, "Proxy app " + pkgName + " location permission changed."
+ + " IsLocationPermissionEnabled: " + updatedLocationPermission);
mProxyAppToLocationPermissions.put(pkgName, updatedLocationPermission);
updateNfwLocationAccessProxyAppsInGnssHal();
}
@@ -192,8 +225,9 @@
mProxyAppToLocationPermissions.clear();
}
- for (String proxApp : nfwLocationAccessProxyApps) {
- mProxyAppToLocationPermissions.put(proxApp, hasLocationPermission(proxApp));
+ for (String proxyAppPkgName : nfwLocationAccessProxyApps) {
+ mProxyAppToLocationPermissions.put(proxyAppPkgName,
+ shouldEnableLocationPermissionInGnssHal(proxyAppPkgName));
}
updateNfwLocationAccessProxyAppsInGnssHal();
@@ -244,6 +278,9 @@
private static final byte NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED = 1;
private static final byte NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED = 2;
+ // This must match with NfwProtocolStack enum in IGnssVisibilityControlCallback.hal.
+ private static final byte NFW_PROTOCOL_STACK_SUPL = 1;
+
private final String mProxyAppPackageName;
private final byte mProtocolStack;
private final String mOtherProtocolStackName;
@@ -293,6 +330,10 @@
return mResponseType != NfwNotification.NFW_RESPONSE_TYPE_REJECTED;
}
+ private boolean isLocationProvided() {
+ return mResponseType == NfwNotification.NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED;
+ }
+
private boolean isRequestAttributedToProxyApp() {
return !TextUtils.isEmpty(mProxyAppPackageName);
}
@@ -300,6 +341,10 @@
private boolean isEmergencyRequestNotification() {
return mInEmergencyMode && !isRequestAttributedToProxyApp();
}
+
+ private boolean isRequestTypeSupl() {
+ return mProtocolStack == NFW_PROTOCOL_STACK_SUPL;
+ }
}
private void handlePermissionsChanged(int uid) {
@@ -308,37 +353,42 @@
}
for (Map.Entry<String, Boolean> entry : mProxyAppToLocationPermissions.entrySet()) {
- // Cannot cache uid since the application could be uninstalled and reinstalled.
- final String proxyApp = entry.getKey();
- final Integer nfwProxyAppUid = getApplicationUid(proxyApp);
- if (nfwProxyAppUid == null || nfwProxyAppUid != uid) {
+ final String proxyAppPkgName = entry.getKey();
+ final ApplicationInfo proxyAppInfo = getProxyAppInfo(proxyAppPkgName);
+ if (proxyAppInfo == null || proxyAppInfo.uid != uid) {
continue;
}
- final boolean isLocationPermissionEnabled = hasLocationPermission(proxyApp);
+ final boolean isLocationPermissionEnabled = shouldEnableLocationPermissionInGnssHal(
+ proxyAppPkgName);
if (isLocationPermissionEnabled != entry.getValue()) {
- Log.i(TAG, "Location permission setting is changed to "
- + (isLocationPermissionEnabled ? "enabled" : "disabled")
- + " for non-framework location access proxy app "
- + proxyApp);
+ Log.i(TAG, "Proxy app " + proxyAppPkgName + " location permission changed."
+ + " IsLocationPermissionEnabled: " + isLocationPermissionEnabled);
entry.setValue(isLocationPermissionEnabled);
updateNfwLocationAccessProxyAppsInGnssHal();
- return;
}
+ return;
}
}
- private Integer getApplicationUid(String pkgName) {
+ private ApplicationInfo getProxyAppInfo(String proxyAppPkgName) {
try {
- return mPackageManager.getApplicationInfo(pkgName, 0).uid;
+ return mPackageManager.getApplicationInfo(proxyAppPkgName, 0);
} catch (PackageManager.NameNotFoundException e) {
- if (DEBUG) {
- Log.d(TAG, "Non-framework location access proxy app " + pkgName + " is not found.");
- }
+ if (DEBUG) Log.d(TAG, "Proxy app " + proxyAppPkgName + " is not found.");
return null;
}
}
+ private boolean shouldEnableLocationPermissionInGnssHal(String proxyAppPkgName) {
+ return isProxyAppInstalled(proxyAppPkgName) && hasLocationPermission(proxyAppPkgName);
+ }
+
+ private boolean isProxyAppInstalled(String pkgName) {
+ ApplicationInfo proxyAppInfo = getProxyAppInfo(pkgName);
+ return (proxyAppInfo != null) && proxyAppInfo.enabled;
+ }
+
private boolean hasLocationPermission(String pkgName) {
return mPackageManager.checkPermission(LOCATION_PERMISSION_NAME, pkgName)
== PackageManager.PERMISSION_GRANTED;
@@ -393,9 +443,9 @@
return;
}
- final String proxyAppPackageName = nfwNotification.mProxyAppPackageName;
+ final String proxyAppPkgName = nfwNotification.mProxyAppPackageName;
final Boolean isLocationPermissionEnabled = mProxyAppToLocationPermissions.get(
- proxyAppPackageName);
+ proxyAppPkgName);
final boolean isLocationRequestAccepted = nfwNotification.isRequestAccepted();
final boolean isPermissionMismatched =
(isLocationPermissionEnabled == null) ? isLocationRequestAccepted
@@ -419,32 +469,31 @@
return;
}
- Log.e(TAG, "ProxyAppPackageName field is not set. AppOps service not notified "
- + "for non-framework location access notification: " + nfwNotification);
+ Log.e(TAG, "ProxyAppPackageName field is not set. AppOps service not notified"
+ + " for notification: " + nfwNotification);
return;
}
if (isLocationPermissionEnabled == null) {
- Log.w(TAG, "Could not find proxy app with name: " + proxyAppPackageName + " in the "
- + "value specified for config parameter: "
- + GnssConfiguration.CONFIG_NFW_PROXY_APPS + ". AppOps service not notified "
- + "for non-framework location access notification: " + nfwNotification);
+ Log.w(TAG, "Could not find proxy app " + proxyAppPkgName + " in the value specified for"
+ + " config parameter: " + GnssConfiguration.CONFIG_NFW_PROXY_APPS
+ + ". AppOps service not notified for notification: " + nfwNotification);
return;
}
// Display location icon attributed to this proxy app.
- final Integer clsAppUid = getApplicationUid(proxyAppPackageName);
- if (clsAppUid == null) {
- Log.e(TAG, "Proxy app " + proxyAppPackageName + " is not found. AppOps service not "
- + "notified for non-framework location access notification: "
- + nfwNotification);
+ final ApplicationInfo proxyAppInfo = getProxyAppInfo(proxyAppPkgName);
+ if (proxyAppInfo == null) {
+ Log.e(TAG, "Proxy app " + proxyAppPkgName + " is not found. AppOps service not "
+ + "notified for notification: " + nfwNotification);
return;
}
- mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, clsAppUid, proxyAppPackageName);
+
+ mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, proxyAppInfo.uid, proxyAppPkgName);
// Log proxy app permission mismatch between framework and GNSS HAL.
if (isPermissionMismatched) {
- Log.w(TAG, "Permission mismatch. Framework proxy app " + proxyAppPackageName
+ Log.w(TAG, "Permission mismatch. Framework proxy app " + proxyAppPkgName
+ " location permission is set to " + isLocationPermissionEnabled
+ " but GNSS non-framework location access response type is "
+ nfwNotification.getResponseTypeAsString() + " for notification: "
@@ -453,13 +502,40 @@
}
private void handleEmergencyNfwNotification(NfwNotification nfwNotification) {
- boolean isPermissionMismatched =
- (nfwNotification.mResponseType == NfwNotification.NFW_RESPONSE_TYPE_REJECTED);
- if (isPermissionMismatched) {
+ boolean isPermissionMismatched = false;
+ if (!nfwNotification.isRequestAccepted()) {
Log.e(TAG, "Emergency non-framework location request incorrectly rejected."
+ " Notification: " + nfwNotification);
+ isPermissionMismatched = true;
}
+
+ if (!mNiHandler.getInEmergency()) {
+ Log.w(TAG, "Emergency state mismatch. Device currently not in user initiated emergency"
+ + " session. Notification: " + nfwNotification);
+ isPermissionMismatched = true;
+ }
+
logEvent(nfwNotification, isPermissionMismatched);
+
+ if (mEsNotify && nfwNotification.isLocationProvided()) {
+ // Emulate deprecated IGnssNi.hal user notification of emergency NI requests.
+ GpsNetInitiatedHandler.GpsNiNotification notification =
+ new GpsNetInitiatedHandler.GpsNiNotification();
+ notification.notificationId = 0;
+ notification.niType = nfwNotification.isRequestTypeSupl()
+ ? GpsNetInitiatedHandler.GPS_NI_TYPE_EMERGENCY_SUPL
+ : GpsNetInitiatedHandler.GPS_NI_TYPE_UMTS_CTRL_PLANE;
+ notification.needNotify = true;
+ notification.needVerify = false;
+ notification.privacyOverride = false;
+ notification.timeout = 0;
+ notification.defaultResponse = GpsNetInitiatedHandler.GPS_NI_RESPONSE_NORESP;
+ notification.requestorId = nfwNotification.mRequestorId;
+ notification.requestorIdEncoding = GpsNetInitiatedHandler.GPS_ENC_NONE;
+ notification.text = mContext.getString(R.string.global_action_emergency);
+ notification.textEncoding = GpsNetInitiatedHandler.GPS_ENC_NONE;
+ mNiHandler.setNiNotification(notification);
+ }
}
private void logEvent(NfwNotification notification, boolean isPermissionMismatched) {
diff --git a/services/core/java/com/android/server/location/GpsXtraDownloader.java b/services/core/java/com/android/server/location/GpsPsdsDownloader.java
similarity index 82%
rename from services/core/java/com/android/server/location/GpsXtraDownloader.java
rename to services/core/java/com/android/server/location/GpsPsdsDownloader.java
index 7dffcb4..6fcb7d1 100644
--- a/services/core/java/com/android/server/location/GpsXtraDownloader.java
+++ b/services/core/java/com/android/server/location/GpsPsdsDownloader.java
@@ -32,26 +32,26 @@
import java.util.concurrent.TimeUnit;
/**
- * A class for downloading GPS XTRA data.
+ * A class for downloading GPS PSDS data.
*
* {@hide}
*/
-public class GpsXtraDownloader {
+public class GpsPsdsDownloader {
- private static final String TAG = "GpsXtraDownloader";
+ private static final String TAG = "GpsPsdsDownloader";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final long MAXIMUM_CONTENT_LENGTH_BYTES = 1000000; // 1MB.
private static final String DEFAULT_USER_AGENT = "Android";
private static final int CONNECTION_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(30);
private static final int READ_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(60);
- private final String[] mXtraServers;
+ private final String[] mPsdsServers;
// to load balance our server requests
private int mNextServerIndex;
private final String mUserAgent;
- GpsXtraDownloader(Properties properties) {
- // read XTRA servers from the Properties object
+ GpsPsdsDownloader(Properties properties) {
+ // read PSDS servers from the Properties object
int count = 0;
String server1 = properties.getProperty("XTRA_SERVER_1");
String server2 = properties.getProperty("XTRA_SERVER_2");
@@ -69,14 +69,14 @@
}
if (count == 0) {
- Log.e(TAG, "No XTRA servers were specified in the GPS configuration");
- mXtraServers = null;
+ Log.e(TAG, "No PSDS servers were specified in the GPS configuration");
+ mPsdsServers = null;
} else {
- mXtraServers = new String[count];
+ mPsdsServers = new String[count];
count = 0;
- if (server1 != null) mXtraServers[count++] = server1;
- if (server2 != null) mXtraServers[count++] = server2;
- if (server3 != null) mXtraServers[count++] = server3;
+ if (server1 != null) mPsdsServers[count++] = server1;
+ if (server2 != null) mPsdsServers[count++] = server2;
+ if (server3 != null) mPsdsServers[count++] = server3;
// randomize first server
Random random = new Random();
@@ -84,11 +84,11 @@
}
}
- byte[] downloadXtraData() {
+ byte[] downloadPsdsData() {
byte[] result = null;
int startIndex = mNextServerIndex;
- if (mXtraServers == null) {
+ if (mPsdsServers == null) {
return null;
}
@@ -97,14 +97,14 @@
final int oldTag = TrafficStats.getAndSetThreadStatsTag(
TrafficStatsConstants.TAG_SYSTEM_GPS);
try {
- result = doDownload(mXtraServers[mNextServerIndex]);
+ result = doDownload(mPsdsServers[mNextServerIndex]);
} finally {
TrafficStats.setThreadStatsTag(oldTag);
}
// increment mNextServerIndex and wrap around if necessary
mNextServerIndex++;
- if (mNextServerIndex == mXtraServers.length) {
+ if (mNextServerIndex == mPsdsServers.length) {
mNextServerIndex = 0;
}
// break if we have tried all the servers
@@ -115,7 +115,7 @@
}
protected byte[] doDownload(String url) {
- if (DEBUG) Log.d(TAG, "Downloading XTRA data from " + url);
+ if (DEBUG) Log.d(TAG, "Downloading PSDS data from " + url);
HttpURLConnection connection = null;
try {
@@ -132,7 +132,7 @@
connection.connect();
int statusCode = connection.getResponseCode();
if (statusCode != HttpURLConnection.HTTP_OK) {
- if (DEBUG) Log.d(TAG, "HTTP error downloading gps XTRA: " + statusCode);
+ if (DEBUG) Log.d(TAG, "HTTP error downloading gps PSDS: " + statusCode);
return null;
}
@@ -143,14 +143,14 @@
while ((count = in.read(buffer)) != -1) {
bytes.write(buffer, 0, count);
if (bytes.size() > MAXIMUM_CONTENT_LENGTH_BYTES) {
- if (DEBUG) Log.d(TAG, "XTRA file too large");
+ if (DEBUG) Log.d(TAG, "PSDS file too large");
return null;
}
}
return bytes.toByteArray();
}
} catch (IOException ioe) {
- if (DEBUG) Log.d(TAG, "Error downloading gps XTRA: ", ioe);
+ if (DEBUG) Log.d(TAG, "Error downloading gps PSDS: ", ioe);
} finally {
if (connection != null) {
connection.disconnect();
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 1b705bb..b246eb6 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -421,8 +421,9 @@
new PasswordSlotManager());
}
- public boolean hasBiometrics() {
- return BiometricManager.hasBiometrics(mContext);
+ public boolean hasEnrolledBiometrics() {
+ BiometricManager bm = mContext.getSystemService(BiometricManager.class);
+ return bm.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS;
}
public int binderGetCallingUid() {
@@ -483,6 +484,12 @@
return;
}
+ if (isUserKeyUnlocked(userId)) {
+ // If storage is not locked, the user will be automatically unlocked so there is
+ // no need to show the notification.
+ return;
+ }
+
final UserHandle userHandle = user.getUserHandle();
final boolean isSecure = isUserSecure(userId);
if (isSecure && !mUserManager.isUserUnlockingOrUnlocked(userHandle)) {
@@ -500,7 +507,7 @@
private void showEncryptionNotificationForProfile(UserHandle user) {
Resources r = mContext.getResources();
CharSequence title = r.getText(
- com.android.internal.R.string.user_encrypted_title);
+ com.android.internal.R.string.profile_encrypted_title);
CharSequence message = r.getText(
com.android.internal.R.string.profile_encrypted_message);
CharSequence detail = r.getText(
@@ -528,7 +535,7 @@
if (!StorageManager.isFileEncryptedNativeOrEmulated()) return;
Notification notification =
- new Notification.Builder(mContext, SystemNotificationChannels.SECURITY)
+ new Notification.Builder(mContext, SystemNotificationChannels.DEVICE_ADMIN)
.setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
.setWhen(0)
.setOngoing(true)
@@ -2496,7 +2503,8 @@
// TODO: When lockout is handled under the HAL for all biometrics (fingerprint),
// we need to generate challenge for each one, have it signed by GK and reset lockout
// for each modality.
- if (!hasChallenge && pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
+ if (!hasChallenge && pm.hasSystemFeature(PackageManager.FEATURE_FACE)
+ && mInjector.hasEnrolledBiometrics()) {
challenge = mContext.getSystemService(FaceManager.class).generateChallenge();
}
@@ -2538,8 +2546,8 @@
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
notifyActivePasswordMetricsAvailable(credentialType, userCredential, userId);
unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
- // Reset lockout
- if (mInjector.hasBiometrics()) {
+ // Reset lockout only if user has enrolled templates
+ if (mInjector.hasEnrolledBiometrics()) {
BiometricManager bm = mContext.getSystemService(BiometricManager.class);
Slog.i(TAG, "Resetting lockout, length: "
+ authResult.gkResponse.getPayload().length);
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index a8c16c7..e2087e6 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -19,12 +19,12 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ParceledListSlice;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioSystem;
import android.media.MediaMetadata;
-import android.media.MediaParceledListSlice;
import android.media.Rating;
import android.media.VolumeProvider;
import android.media.session.ISession;
@@ -84,7 +84,7 @@
private final MediaSession.Token mSessionToken;
private final SessionStub mSession;
private final SessionCb mSessionCb;
- private final MediaSessionService.ServiceImpl mService;
+ private final MediaSessionService mService;
private final Context mContext;
private final Object mLock = new Object();
@@ -125,7 +125,7 @@
public MediaSessionRecord(int ownerPid, int ownerUid, int userId, String ownerPackageName,
ISessionCallback cb, String tag, Bundle sessionInfo,
- MediaSessionService.ServiceImpl service, Looper handlerLooper) {
+ MediaSessionService service, Looper handlerLooper) {
mOwnerPid = ownerPid;
mOwnerUid = ownerUid;
mUserId = userId;
@@ -612,7 +612,7 @@
ISessionControllerCallbackHolder holder = mControllerCallbackHolders.get(i);
try {
holder.mCallback.onQueueChanged(mQueue == null ? null :
- new MediaParceledListSlice<>(mQueue));
+ new ParceledListSlice<>(mQueue));
} catch (DeadObjectException e) {
mControllerCallbackHolders.remove(i);
logCallbackException("Removing dead callback in pushQueueUpdate", holder, e);
@@ -904,7 +904,7 @@
}
@Override
- public void setQueue(MediaParceledListSlice queue) throws RemoteException {
+ public void setQueue(ParceledListSlice queue) throws RemoteException {
synchronized (mLock) {
mQueue = queue == null ? null : (List<QueueItem>) queue.getList();
}
@@ -1469,9 +1469,9 @@
}
@Override
- public MediaParceledListSlice getQueue() {
+ public ParceledListSlice getQueue() {
synchronized (mLock) {
- return mQueue == null ? null : new MediaParceledListSlice<>(mQueue);
+ return mQueue == null ? null : new ParceledListSlice<>(mQueue);
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index d20ed8c..adc1561 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -16,15 +16,81 @@
package com.android.server.media;
-import android.content.Context;
-import android.media.Session2Token;
-import android.os.IBinder;
-import android.util.Log;
+import static android.os.UserHandle.USER_ALL;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.INotificationManager;
+import android.app.KeyguardManager;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.media.AudioManager;
+import android.media.AudioManagerInternal;
+import android.media.AudioPlaybackConfiguration;
+import android.media.AudioSystem;
+import android.media.IAudioService;
+import android.media.IRemoteVolumeController;
+import android.media.MediaController2;
+import android.media.Session2CommandGroup;
+import android.media.Session2Token;
+import android.media.session.IActiveSessionsListener;
+import android.media.session.ICallback;
+import android.media.session.IOnMediaKeyListener;
+import android.media.session.IOnVolumeKeyLongPressListener;
+import android.media.session.ISession;
+import android.media.session.ISession2TokensListener;
+import android.media.session.ISessionCallback;
+import android.media.session.ISessionManager;
+import android.media.session.MediaSession;
+import android.media.session.MediaSessionManager;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.speech.RecognizerIntent;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.view.KeyEvent;
+import android.view.ViewConfiguration;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.Watchdog;
import com.android.server.Watchdog.Monitor;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -33,124 +99,2168 @@
public class MediaSessionService extends SystemService implements Monitor {
private static final String TAG = "MediaSessionService";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ // Leave log for key event always.
+ private static final boolean DEBUG_KEY_EVENT = true;
- private final ServiceImpl mImpl;
+ private static final int WAKELOCK_TIMEOUT = 5000;
+ private static final int MEDIA_KEY_LISTENER_TIMEOUT = 1000;
+
+ private final Context mContext;
+ private final SessionManagerImpl mSessionManagerImpl;
+ private final MessageHandler mHandler = new MessageHandler();
+ private final PowerManager.WakeLock mMediaEventWakeLock;
+ private final int mLongPressTimeout;
+ private final INotificationManager mNotificationManager;
+ private final Object mLock = new Object();
+ // Keeps the full user id for each user.
+ @GuardedBy("mLock")
+ private final SparseIntArray mFullUserIds = new SparseIntArray();
+ @GuardedBy("mLock")
+ private final SparseArray<FullUserRecord> mUserRecords = new SparseArray<FullUserRecord>();
+ @GuardedBy("mLock")
+ private final ArrayList<SessionsListenerRecord> mSessionsListeners =
+ new ArrayList<SessionsListenerRecord>();
+ // Map user id as index to list of Session2Tokens
+ // TODO: Keep session2 info in MediaSessionStack for prioritizing both session1 and session2 in
+ // one place.
+ @GuardedBy("mLock")
+ private final SparseArray<List<Session2Token>> mSession2TokensPerUser = new SparseArray<>();
+ @GuardedBy("mLock")
+ private final List<Session2TokensListenerRecord> mSession2TokensListenerRecords =
+ new ArrayList<>();
+
+ private KeyguardManager mKeyguardManager;
+ private IAudioService mAudioService;
+ private AudioManagerInternal mAudioManagerInternal;
+ private ActivityManager mActivityManager;
+ private ContentResolver mContentResolver;
+ private SettingsObserver mSettingsObserver;
+ private boolean mHasFeatureLeanback;
+
+ // The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile)
+ // It's always not null after the MediaSessionService is started.
+ private FullUserRecord mCurrentFullUserRecord;
+ private MediaSessionRecord mGlobalPrioritySession;
+ private AudioPlayerStateMonitor mAudioPlayerStateMonitor;
+
+ // Used to notify System UI and Settings when remote volume was changed.
+ @GuardedBy("mLock")
+ final RemoteCallbackList<IRemoteVolumeController> mRemoteVolumeControllers =
+ new RemoteCallbackList<>();
public MediaSessionService(Context context) {
super(context);
- mImpl = new MediaSessionServiceImpl(context);
+ mContext = context;
+ mSessionManagerImpl = new SessionManagerImpl();
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent");
+ mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
+ mNotificationManager = INotificationManager.Stub.asInterface(
+ ServiceManager.getService(Context.NOTIFICATION_SERVICE));
}
@Override
public void onStart() {
- publishBinderService(Context.MEDIA_SESSION_SERVICE, mImpl.getServiceBinder());
+ publishBinderService(Context.MEDIA_SESSION_SERVICE, mSessionManagerImpl);
Watchdog.getInstance().addMonitor(this);
+ mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+ mAudioService = getAudioService();
+ mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
+ mActivityManager =
+ (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(mContext);
+ mAudioPlayerStateMonitor.registerListener(
+ (config, isRemoved) -> {
+ if (config.getPlayerType()
+ == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
+ return;
+ }
+ synchronized (mLock) {
+ FullUserRecord user = getFullUserRecordLocked(
+ UserHandle.getUserId(config.getClientUid()));
+ if (user != null) {
+ user.mPriorityStack.updateMediaButtonSessionIfNeeded();
+ }
+ }
+ }, null /* handler */);
+ mContentResolver = mContext.getContentResolver();
+ mSettingsObserver = new SettingsObserver();
+ mSettingsObserver.observe();
+ mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_LEANBACK);
+ updateUser();
+ }
- mImpl.onStart();
+ private IAudioService getAudioService() {
+ IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+ return IAudioService.Stub.asInterface(b);
+ }
+
+ private boolean isGlobalPriorityActiveLocked() {
+ return mGlobalPrioritySession != null && mGlobalPrioritySession.isActive();
+ }
+
+ void updateSession(MediaSessionRecord record) {
+ synchronized (mLock) {
+ FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+ if (user == null) {
+ Log.w(TAG, "Unknown session updated. Ignoring.");
+ return;
+ }
+ if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "Global priority session is updated, active=" + record.isActive());
+ }
+ user.pushAddressedPlayerChangedLocked();
+ } else {
+ if (!user.mPriorityStack.contains(record)) {
+ Log.w(TAG, "Unknown session updated. Ignoring.");
+ return;
+ }
+ user.mPriorityStack.onSessionStateChange(record);
+ }
+ mHandler.postSessionsChanged(record.getUserId());
+ }
+ }
+
+ void setGlobalPrioritySession(MediaSessionRecord record) {
+ synchronized (mLock) {
+ FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+ if (mGlobalPrioritySession != record) {
+ Log.d(TAG, "Global priority session is changed from " + mGlobalPrioritySession
+ + " to " + record);
+ mGlobalPrioritySession = record;
+ if (user != null && user.mPriorityStack.contains(record)) {
+ // Handle the global priority session separately.
+ // Otherwise, it can be the media button session regardless of the active state
+ // because it or other system components might have been the lastly played media
+ // app.
+ user.mPriorityStack.removeSession(record);
+ }
+ }
+ }
+ }
+
+ private List<MediaSessionRecord> getActiveSessionsLocked(int userId) {
+ List<MediaSessionRecord> records = new ArrayList<>();
+ if (userId == USER_ALL) {
+ int size = mUserRecords.size();
+ for (int i = 0; i < size; i++) {
+ records.addAll(mUserRecords.valueAt(i).mPriorityStack.getActiveSessions(userId));
+ }
+ } else {
+ FullUserRecord user = getFullUserRecordLocked(userId);
+ if (user == null) {
+ Log.w(TAG, "getSessions failed. Unknown user " + userId);
+ return records;
+ }
+ records.addAll(user.mPriorityStack.getActiveSessions(userId));
+ }
+
+ // Return global priority session at the first whenever it's asked.
+ if (isGlobalPriorityActiveLocked()
+ && (userId == USER_ALL || userId == mGlobalPrioritySession.getUserId())) {
+ records.add(0, mGlobalPrioritySession);
+ }
+ return records;
+ }
+
+ List<Session2Token> getSession2TokensLocked(int userId) {
+ List<Session2Token> list = new ArrayList<>();
+ if (userId == USER_ALL) {
+ for (int i = 0; i < mSession2TokensPerUser.size(); i++) {
+ list.addAll(mSession2TokensPerUser.valueAt(i));
+ }
+ } else {
+ list.addAll(mSession2TokensPerUser.get(userId));
+ }
+ return list;
+ }
+
+ /**
+ * Tells the System UI and Settings app that volume has changed on an active remote session.
+ */
+ public void notifyRemoteVolumeChanged(int flags, MediaSessionRecord session) {
+ if (!session.isActive()) {
+ return;
+ }
+ synchronized (mLock) {
+ int size = mRemoteVolumeControllers.beginBroadcast();
+ MediaSession.Token token = session.getSessionToken();
+ for (int i = size - 1; i >= 0; i--) {
+ try {
+ IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
+ cb.remoteVolumeChanged(token, flags);
+ } catch (Exception e) {
+ Log.w(TAG, "Error sending volume change.", e);
+ }
+ }
+ mRemoteVolumeControllers.finishBroadcast();
+ }
+ }
+
+ void onSessionPlaystateChanged(MediaSessionRecord record, int oldState, int newState) {
+ synchronized (mLock) {
+ FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+ if (user == null || !user.mPriorityStack.contains(record)) {
+ Log.d(TAG, "Unknown session changed playback state. Ignoring.");
+ return;
+ }
+ user.mPriorityStack.onPlaystateChanged(record, oldState, newState);
+ }
+ }
+
+ void onSessionPlaybackTypeChanged(MediaSessionRecord record) {
+ synchronized (mLock) {
+ FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+ if (user == null || !user.mPriorityStack.contains(record)) {
+ Log.d(TAG, "Unknown session changed playback type. Ignoring.");
+ return;
+ }
+ pushRemoteVolumeUpdateLocked(record.getUserId());
+ }
}
@Override
public void onStartUser(int userId) {
- mImpl.onStartUser(userId);
+ if (DEBUG) Log.d(TAG, "onStartUser: " + userId);
+ updateUser();
}
@Override
public void onSwitchUser(int userId) {
- mImpl.onSwitchUser(userId);
+ if (DEBUG) Log.d(TAG, "onSwitchUser: " + userId);
+ updateUser();
}
// Called when the user with the userId is removed.
@Override
public void onStopUser(int userId) {
- mImpl.onStopUser(userId);
+ if (DEBUG) Log.d(TAG, "onStopUser: " + userId);
+ synchronized (mLock) {
+ // TODO: Also handle removing user in updateUser() because adding/switching user is
+ // handled in updateUser().
+ FullUserRecord user = getFullUserRecordLocked(userId);
+ if (user != null) {
+ if (user.mFullUserId == userId) {
+ user.destroySessionsForUserLocked(USER_ALL);
+ mUserRecords.remove(userId);
+ } else {
+ user.destroySessionsForUserLocked(userId);
+ }
+ }
+ mSession2TokensPerUser.remove(userId);
+ updateUser();
+ }
}
@Override
public void monitor() {
- mImpl.monitor();
- }
-
- /**
- * Updates session.
- */
- public void updateSession(MediaSessionRecord record) {
- mImpl.updateSession(record);
- }
-
- /**
- * Sets global priority session.
- */
- public void setGlobalPrioritySession(MediaSessionRecord record) {
- mImpl.setGlobalPrioritySession(record);
- }
-
- List<Session2Token> getSession2TokensLocked(int userId) {
- return mImpl.getSession2TokensLocked(userId);
- }
-
- /**
- * Tells the system UI that volume has changed on an active remote session.
- */
- public void notifyRemoteVolumeChanged(int flags, MediaSessionRecord session) {
- mImpl.notifyRemoteVolumeChanged(flags, session);
- }
-
- /**
- * Called when session playstate is changed.
- */
- public void onSessionPlaystateChanged(MediaSessionRecord record, int oldState, int newState) {
- mImpl.onSessionPlaystateChanged(record, oldState, newState);
- }
-
- /**
- * Called when session playback type is changed.
- */
- public void onSessionPlaybackTypeChanged(MediaSessionRecord record) {
- mImpl.onSessionPlaybackTypeChanged(record);
+ synchronized (mLock) {
+ // Check for deadlock
+ }
}
protected void enforcePhoneStatePermission(int pid, int uid) {
- mImpl.enforcePhoneStatePermission(pid, uid);
+ if (mContext.checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE, pid, uid)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold the MODIFY_PHONE_STATE permission.");
+ }
}
void sessionDied(MediaSessionRecord session) {
- mImpl.sessionDied(session);
+ synchronized (mLock) {
+ destroySessionLocked(session);
+ }
}
void destroySession(MediaSessionRecord session) {
- mImpl.destroySession(session);
+ synchronized (mLock) {
+ destroySessionLocked(session);
+ }
}
- void pushSession2TokensChangedLocked(int userId) {
- mImpl.pushSession2TokensChangedLocked(userId);
+ private void updateUser() {
+ synchronized (mLock) {
+ UserManager manager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mFullUserIds.clear();
+ List<UserInfo> allUsers = manager.getUsers();
+ if (allUsers != null) {
+ for (UserInfo userInfo : allUsers) {
+ if (userInfo.isManagedProfile()) {
+ mFullUserIds.put(userInfo.id, userInfo.profileGroupId);
+ } else {
+ mFullUserIds.put(userInfo.id, userInfo.id);
+ if (mUserRecords.get(userInfo.id) == null) {
+ mUserRecords.put(userInfo.id, new FullUserRecord(userInfo.id));
+ }
+ }
+ if (mSession2TokensPerUser.get(userInfo.id) == null) {
+ mSession2TokensPerUser.put(userInfo.id, new ArrayList<>());
+ }
+ }
+ }
+ // Ensure that the current full user exists.
+ int currentFullUserId = ActivityManager.getCurrentUser();
+ mCurrentFullUserRecord = mUserRecords.get(currentFullUserId);
+ if (mCurrentFullUserRecord == null) {
+ Log.w(TAG, "Cannot find FullUserInfo for the current user " + currentFullUserId);
+ mCurrentFullUserRecord = new FullUserRecord(currentFullUserId);
+ mUserRecords.put(currentFullUserId, mCurrentFullUserRecord);
+ if (mSession2TokensPerUser.get(currentFullUserId) == null) {
+ mSession2TokensPerUser.put(currentFullUserId, new ArrayList<>());
+ }
+ }
+ mFullUserIds.put(currentFullUserId, currentFullUserId);
+ }
+ }
+
+ private void updateActiveSessionListeners() {
+ synchronized (mLock) {
+ for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
+ SessionsListenerRecord listener = mSessionsListeners.get(i);
+ try {
+ enforceMediaPermissions(listener.componentName, listener.pid, listener.uid,
+ listener.userId);
+ } catch (SecurityException e) {
+ Log.i(TAG, "ActiveSessionsListener " + listener.componentName
+ + " is no longer authorized. Disconnecting.");
+ mSessionsListeners.remove(i);
+ try {
+ listener.listener
+ .onActiveSessionsChanged(new ArrayList<MediaSession.Token>());
+ } catch (Exception e1) {
+ // ignore
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * When a session is removed several things need to happen.
+ * 1. We need to remove it from the relevant user.
+ * 2. We need to remove it from the priority stack.
+ * 3. We need to remove it from all sessions.
+ * 4. If this is the system priority session we need to clear it.
+ * 5. We need to unlink to death from the cb binder
+ * 6. We need to tell the session to do any final cleanup (onDestroy)
+ */
+ private void destroySessionLocked(MediaSessionRecord session) {
+ if (DEBUG) {
+ Log.d(TAG, "Destroying " + session);
+ }
+ FullUserRecord user = getFullUserRecordLocked(session.getUserId());
+ if (mGlobalPrioritySession == session) {
+ mGlobalPrioritySession = null;
+ if (session.isActive() && user != null) {
+ user.pushAddressedPlayerChangedLocked();
+ }
+ } else {
+ if (user != null) {
+ user.mPriorityStack.removeSession(session);
+ }
+ }
+
+ try {
+ session.getCallback().asBinder().unlinkToDeath(session, 0);
+ } catch (Exception e) {
+ // ignore exceptions while destroying a session.
+ }
+ session.onDestroy();
+ mHandler.postSessionsChanged(session.getUserId());
+ }
+
+ private void enforcePackageName(String packageName, int uid) {
+ if (TextUtils.isEmpty(packageName)) {
+ throw new IllegalArgumentException("packageName may not be empty");
+ }
+ String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
+ final int packageCount = packages.length;
+ for (int i = 0; i < packageCount; i++) {
+ if (packageName.equals(packages[i])) {
+ return;
+ }
+ }
+ throw new IllegalArgumentException("packageName is not owned by the calling process");
}
/**
- * Called when media button receiver changed.
+ * Checks a caller's authorization to register an IRemoteControlDisplay.
+ * Authorization is granted if one of the following is true:
+ * <ul>
+ * <li>the caller has android.Manifest.permission.MEDIA_CONTENT_CONTROL
+ * permission</li>
+ * <li>the caller's listener is one of the enabled notification listeners
+ * for the caller's user</li>
+ * </ul>
*/
- public void onMediaButtonReceiverChanged(MediaSessionRecord record) {
- mImpl.onMediaButtonReceiverChanged(record);
+ private void enforceMediaPermissions(ComponentName compName, int pid, int uid,
+ int resolvedUserId) {
+ if (hasStatusBarServicePermission(pid, uid)) return;
+ if (mContext
+ .checkPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
+ != PackageManager.PERMISSION_GRANTED
+ && !isEnabledNotificationListener(compName, UserHandle.getUserId(uid),
+ resolvedUserId)) {
+ throw new SecurityException("Missing permission to control media.");
+ }
}
- abstract static class ServiceImpl {
- public abstract void onStart();
- public abstract void notifyRemoteVolumeChanged(int flags, MediaSessionRecord session);
- public abstract void onSessionPlaystateChanged(
- MediaSessionRecord record, int oldState, int newState);
- public abstract void onSessionPlaybackTypeChanged(MediaSessionRecord record);
- public abstract void onStartUser(int userId);
- public abstract void onSwitchUser(int userId);
- public abstract void monitor();
- public abstract void onMediaButtonReceiverChanged(MediaSessionRecord record);
- protected abstract void enforcePhoneStatePermission(int pid, int uid);
- abstract void updateSession(MediaSessionRecord record);
- abstract void setGlobalPrioritySession(MediaSessionRecord record);
- abstract List<Session2Token> getSession2TokensLocked(int userId);
- abstract void onStopUser(int userId);
- abstract void sessionDied(MediaSessionRecord session);
- abstract void destroySession(MediaSessionRecord session);
- abstract void pushSession2TokensChangedLocked(int userId);
- abstract Context getContext();
- abstract IBinder getServiceBinder();
+ private boolean hasStatusBarServicePermission(int pid, int uid) {
+ return mContext.checkPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
+ pid, uid) == PackageManager.PERMISSION_GRANTED;
+ }
+
+ private void enforceStatusBarServicePermission(String action, int pid, int uid) {
+ if (!hasStatusBarServicePermission(pid, uid)) {
+ throw new SecurityException("Only System UI and Settings may " + action);
+ }
+ }
+
+ /**
+ * This checks if the component is an enabled notification listener for the
+ * specified user. Enabled components may only operate on behalf of the user
+ * they're running as.
+ *
+ * @param compName The component that is enabled.
+ * @param userId The user id of the caller.
+ * @param forUserId The user id they're making the request on behalf of.
+ * @return True if the component is enabled, false otherwise
+ */
+ private boolean isEnabledNotificationListener(ComponentName compName, int userId,
+ int forUserId) {
+ if (userId != forUserId) {
+ // You may not access another user's content as an enabled listener.
+ return false;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Checking if enabled notification listener " + compName);
+ }
+ if (compName != null) {
+ try {
+ return mNotificationManager.isNotificationListenerAccessGrantedForUser(
+ compName, userId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Dead NotificationManager in isEnabledNotificationListener", e);
+ }
+ }
+ return false;
+ }
+
+ private MediaSessionRecord createSessionInternal(int callerPid, int callerUid, int userId,
+ String callerPackageName, ISessionCallback cb, String tag, Bundle sessionInfo)
+ throws RemoteException {
+ synchronized (mLock) {
+ return createSessionLocked(callerPid, callerUid, userId, callerPackageName, cb,
+ tag, sessionInfo);
+ }
+ }
+
+ /*
+ * When a session is created the following things need to happen.
+ * 1. Its callback binder needs a link to death
+ * 2. It needs to be added to all sessions.
+ * 3. It needs to be added to the priority stack.
+ * 4. It needs to be added to the relevant user record.
+ */
+ private MediaSessionRecord createSessionLocked(int callerPid, int callerUid, int userId,
+ String callerPackageName, ISessionCallback cb, String tag, Bundle sessionInfo) {
+ FullUserRecord user = getFullUserRecordLocked(userId);
+ if (user == null) {
+ Log.w(TAG, "Request from invalid user: " + userId + ", pkg=" + callerPackageName);
+ throw new RuntimeException("Session request from invalid user.");
+ }
+
+ final MediaSessionRecord session = new MediaSessionRecord(callerPid, callerUid, userId,
+ callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper());
+ try {
+ cb.asBinder().linkToDeath(session, 0);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Media Session owner died prematurely.", e);
+ }
+
+ user.mPriorityStack.addSession(session);
+ mHandler.postSessionsChanged(userId);
+
+ if (DEBUG) {
+ Log.d(TAG, "Created session for " + callerPackageName + " with tag " + tag);
+ }
+ return session;
+ }
+
+ private int findIndexOfSessionsListenerLocked(IActiveSessionsListener listener) {
+ for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
+ if (mSessionsListeners.get(i).listener.asBinder() == listener.asBinder()) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private int findIndexOfSession2TokensListenerLocked(ISession2TokensListener listener) {
+ for (int i = mSession2TokensListenerRecords.size() - 1; i >= 0; i--) {
+ if (mSession2TokensListenerRecords.get(i).listener.asBinder() == listener.asBinder()) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private void pushSessionsChanged(int userId) {
+ synchronized (mLock) {
+ FullUserRecord user = getFullUserRecordLocked(userId);
+ if (user == null) {
+ Log.w(TAG, "pushSessionsChanged failed. No user with id=" + userId);
+ return;
+ }
+ List<MediaSessionRecord> records = getActiveSessionsLocked(userId);
+ int size = records.size();
+ ArrayList<MediaSession.Token> tokens = new ArrayList<MediaSession.Token>();
+ for (int i = 0; i < size; i++) {
+ tokens.add(records.get(i).getSessionToken());
+ }
+ pushRemoteVolumeUpdateLocked(userId);
+ for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
+ SessionsListenerRecord record = mSessionsListeners.get(i);
+ if (record.userId == USER_ALL || record.userId == userId) {
+ try {
+ record.listener.onActiveSessionsChanged(tokens);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Dead ActiveSessionsListener in pushSessionsChanged, removing",
+ e);
+ mSessionsListeners.remove(i);
+ }
+ }
+ }
+ }
+ }
+
+ private void pushRemoteVolumeUpdateLocked(int userId) {
+ FullUserRecord user = getFullUserRecordLocked(userId);
+ if (user == null) {
+ Log.w(TAG, "pushRemoteVolumeUpdateLocked failed. No user with id=" + userId);
+ return;
+ }
+
+ synchronized (mLock) {
+ int size = mRemoteVolumeControllers.beginBroadcast();
+ MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
+ MediaSession.Token token = record == null ? null : record.getSessionToken();
+
+ for (int i = size - 1; i >= 0; i--) {
+ try {
+ IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
+ cb.updateRemoteController(token);
+ } catch (Exception e) {
+ Log.w(TAG, "Error sending default remote volume.", e);
+ }
+ }
+ mRemoteVolumeControllers.finishBroadcast();
+ }
+ }
+
+ void pushSession2TokensChangedLocked(int userId) {
+ List<Session2Token> allSession2Tokens = getSession2TokensLocked(USER_ALL);
+ List<Session2Token> session2Tokens = getSession2TokensLocked(userId);
+
+ for (int i = mSession2TokensListenerRecords.size() - 1; i >= 0; i--) {
+ Session2TokensListenerRecord listenerRecord = mSession2TokensListenerRecords.get(i);
+ try {
+ if (listenerRecord.userId == USER_ALL) {
+ listenerRecord.listener.onSession2TokensChanged(allSession2Tokens);
+ } else if (listenerRecord.userId == userId) {
+ listenerRecord.listener.onSession2TokensChanged(session2Tokens);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to notify Session2Token change. Removing listener.", e);
+ mSession2TokensListenerRecords.remove(i);
+ }
+ }
+ }
+
+ /**
+ * Called when the media button receiver for the {@code record} is changed.
+ *
+ * @param record the media session whose media button receiver is updated.
+ */
+ public void onMediaButtonReceiverChanged(MediaSessionRecord record) {
+ synchronized (mLock) {
+ FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+ MediaSessionRecord mediaButtonSession =
+ user.mPriorityStack.getMediaButtonSession();
+ if (record == mediaButtonSession) {
+ user.rememberMediaButtonReceiverLocked(mediaButtonSession);
+ }
+ }
+ }
+
+ private String getCallingPackageName(int uid) {
+ String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
+ if (packages != null && packages.length > 0) {
+ return packages[0];
+ }
+ return "";
+ }
+
+ private void dispatchVolumeKeyLongPressLocked(KeyEvent keyEvent) {
+ if (mCurrentFullUserRecord.mOnVolumeKeyLongPressListener == null) {
+ return;
+ }
+ try {
+ mCurrentFullUserRecord.mOnVolumeKeyLongPressListener.onVolumeKeyLongPress(keyEvent);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send " + keyEvent + " to volume key long-press listener");
+ }
+ }
+
+ private FullUserRecord getFullUserRecordLocked(int userId) {
+ int fullUserId = mFullUserIds.get(userId, -1);
+ if (fullUserId < 0) {
+ return null;
+ }
+ return mUserRecords.get(fullUserId);
+ }
+
+ private MediaSessionRecord getMediaSessionRecordLocked(MediaSession.Token sessionToken) {
+ FullUserRecord user = getFullUserRecordLocked(UserHandle.getUserId(sessionToken.getUid()));
+ if (user != null) {
+ return user.mPriorityStack.getMediaSessionRecord(sessionToken);
+ }
+ return null;
+ }
+
+ /**
+ * Information about a full user and its corresponding managed profiles.
+ *
+ * <p>Since the full user runs together with its managed profiles, a user wouldn't differentiate
+ * them when he/she presses a media/volume button. So keeping media sessions for them in one
+ * place makes more sense and increases the readability.</p>
+ * <p>The contents of this object is guarded by {@link #mLock}.
+ */
+ final class FullUserRecord implements MediaSessionStack.OnMediaButtonSessionChangedListener {
+ public static final int COMPONENT_TYPE_INVALID = 0;
+ public static final int COMPONENT_TYPE_BROADCAST = 1;
+ public static final int COMPONENT_TYPE_ACTIVITY = 2;
+ public static final int COMPONENT_TYPE_SERVICE = 3;
+ private static final String COMPONENT_NAME_USER_ID_DELIM = ",";
+
+ private final int mFullUserId;
+ private final MediaSessionStack mPriorityStack;
+ private PendingIntent mLastMediaButtonReceiver;
+ private ComponentName mRestoredMediaButtonReceiver;
+ private int mRestoredMediaButtonReceiverComponentType;
+ private int mRestoredMediaButtonReceiverUserId;
+
+ private IOnVolumeKeyLongPressListener mOnVolumeKeyLongPressListener;
+ private int mOnVolumeKeyLongPressListenerUid;
+ private KeyEvent mInitialDownVolumeKeyEvent;
+ private int mInitialDownVolumeStream;
+ private boolean mInitialDownMusicOnly;
+
+ private IOnMediaKeyListener mOnMediaKeyListener;
+ private int mOnMediaKeyListenerUid;
+ private ICallback mCallback;
+
+ FullUserRecord(int fullUserId) {
+ mFullUserId = fullUserId;
+ mPriorityStack = new MediaSessionStack(mAudioPlayerStateMonitor, this);
+ // Restore the remembered media button receiver before the boot.
+ String mediaButtonReceiverInfo = Settings.Secure.getStringForUser(mContentResolver,
+ Settings.System.MEDIA_BUTTON_RECEIVER, mFullUserId);
+ if (mediaButtonReceiverInfo == null) {
+ return;
+ }
+ String[] tokens = mediaButtonReceiverInfo.split(COMPONENT_NAME_USER_ID_DELIM);
+ if (tokens == null || (tokens.length != 2 && tokens.length != 3)) {
+ return;
+ }
+ mRestoredMediaButtonReceiver = ComponentName.unflattenFromString(tokens[0]);
+ mRestoredMediaButtonReceiverUserId = Integer.parseInt(tokens[1]);
+ if (tokens.length == 3) {
+ mRestoredMediaButtonReceiverComponentType = Integer.parseInt(tokens[2]);
+ } else {
+ mRestoredMediaButtonReceiverComponentType =
+ getComponentType(mRestoredMediaButtonReceiver);
+ }
+ }
+
+ public void destroySessionsForUserLocked(int userId) {
+ List<MediaSessionRecord> sessions = mPriorityStack.getPriorityList(false, userId);
+ for (MediaSessionRecord session : sessions) {
+ destroySessionLocked(session);
+ }
+ }
+
+ public void dumpLocked(PrintWriter pw, String prefix) {
+ pw.print(prefix + "Record for full_user=" + mFullUserId);
+ // Dump managed profile user ids associated with this user.
+ int size = mFullUserIds.size();
+ for (int i = 0; i < size; i++) {
+ if (mFullUserIds.keyAt(i) != mFullUserIds.valueAt(i)
+ && mFullUserIds.valueAt(i) == mFullUserId) {
+ pw.print(", profile_user=" + mFullUserIds.keyAt(i));
+ }
+ }
+ pw.println();
+ String indent = prefix + " ";
+ pw.println(indent + "Volume key long-press listener: " + mOnVolumeKeyLongPressListener);
+ pw.println(indent + "Volume key long-press listener package: "
+ + getCallingPackageName(mOnVolumeKeyLongPressListenerUid));
+ pw.println(indent + "Media key listener: " + mOnMediaKeyListener);
+ pw.println(indent + "Media key listener package: "
+ + getCallingPackageName(mOnMediaKeyListenerUid));
+ pw.println(indent + "Callback: " + mCallback);
+ pw.println(indent + "Last MediaButtonReceiver: " + mLastMediaButtonReceiver);
+ pw.println(indent + "Restored MediaButtonReceiver: " + mRestoredMediaButtonReceiver);
+ pw.println(indent + "Restored MediaButtonReceiverComponentType: "
+ + mRestoredMediaButtonReceiverComponentType);
+ mPriorityStack.dump(pw, indent);
+ pw.println(indent + "Session2Tokens:");
+ for (int i = 0; i < mSession2TokensPerUser.size(); i++) {
+ List<Session2Token> list = mSession2TokensPerUser.valueAt(i);
+ if (list == null || list.size() == 0) {
+ continue;
+ }
+ for (Session2Token token : list) {
+ pw.println(indent + " " + token);
+ }
+ }
+ }
+
+ @Override
+ public void onMediaButtonSessionChanged(MediaSessionRecord oldMediaButtonSession,
+ MediaSessionRecord newMediaButtonSession) {
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "Media button session is changed to " + newMediaButtonSession);
+ }
+ synchronized (mLock) {
+ if (oldMediaButtonSession != null) {
+ mHandler.postSessionsChanged(oldMediaButtonSession.getUserId());
+ }
+ if (newMediaButtonSession != null) {
+ rememberMediaButtonReceiverLocked(newMediaButtonSession);
+ mHandler.postSessionsChanged(newMediaButtonSession.getUserId());
+ }
+ pushAddressedPlayerChangedLocked();
+ }
+ }
+
+ // Remember media button receiver and keep it in the persistent storage.
+ public void rememberMediaButtonReceiverLocked(MediaSessionRecord record) {
+ PendingIntent receiver = record.getMediaButtonReceiver();
+ mLastMediaButtonReceiver = receiver;
+ mRestoredMediaButtonReceiver = null;
+ mRestoredMediaButtonReceiverComponentType = COMPONENT_TYPE_INVALID;
+
+ String mediaButtonReceiverInfo = "";
+ if (receiver != null) {
+ ComponentName component = receiver.getIntent().getComponent();
+ if (component != null
+ && record.getPackageName().equals(component.getPackageName())) {
+ String componentName = component.flattenToString();
+ int componentType = getComponentType(component);
+ mediaButtonReceiverInfo = String.join(COMPONENT_NAME_USER_ID_DELIM,
+ componentName, String.valueOf(record.getUserId()),
+ String.valueOf(componentType));
+ }
+ }
+ Settings.Secure.putStringForUser(mContentResolver,
+ Settings.System.MEDIA_BUTTON_RECEIVER, mediaButtonReceiverInfo,
+ mFullUserId);
+ }
+
+ private void pushAddressedPlayerChangedLocked() {
+ if (mCallback == null) {
+ return;
+ }
+ try {
+ MediaSessionRecord mediaButtonSession = getMediaButtonSessionLocked();
+ if (mediaButtonSession != null) {
+ mCallback.onAddressedPlayerChangedToMediaSession(
+ mediaButtonSession.getSessionToken());
+ } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
+ mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
+ mCurrentFullUserRecord.mLastMediaButtonReceiver
+ .getIntent().getComponent());
+ } else if (mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
+ mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
+ mCurrentFullUserRecord.mRestoredMediaButtonReceiver);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to pushAddressedPlayerChangedLocked", e);
+ }
+ }
+
+ private MediaSessionRecord getMediaButtonSessionLocked() {
+ return isGlobalPriorityActiveLocked()
+ ? mGlobalPrioritySession : mPriorityStack.getMediaButtonSession();
+ }
+
+ private int getComponentType(@Nullable ComponentName componentName) {
+ if (componentName == null) {
+ return COMPONENT_TYPE_INVALID;
+ }
+ PackageManager pm = mContext.getPackageManager();
+ try {
+ ActivityInfo activityInfo = pm.getActivityInfo(componentName,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.GET_ACTIVITIES);
+ if (activityInfo != null) {
+ return COMPONENT_TYPE_ACTIVITY;
+ }
+ } catch (NameNotFoundException e) {
+ }
+ try {
+ ServiceInfo serviceInfo = pm.getServiceInfo(componentName,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.GET_SERVICES);
+ if (serviceInfo != null) {
+ return COMPONENT_TYPE_SERVICE;
+ }
+ } catch (NameNotFoundException e) {
+ }
+ // Pick legacy behavior for BroadcastReceiver or unknown.
+ return COMPONENT_TYPE_BROADCAST;
+ }
+ }
+
+ final class SessionsListenerRecord implements IBinder.DeathRecipient {
+ public final IActiveSessionsListener listener;
+ public final ComponentName componentName;
+ public final int userId;
+ public final int pid;
+ public final int uid;
+
+ SessionsListenerRecord(IActiveSessionsListener listener,
+ ComponentName componentName,
+ int userId, int pid, int uid) {
+ this.listener = listener;
+ this.componentName = componentName;
+ this.userId = userId;
+ this.pid = pid;
+ this.uid = uid;
+ }
+
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ mSessionsListeners.remove(this);
+ }
+ }
+ }
+
+ final class Session2TokensListenerRecord implements IBinder.DeathRecipient {
+ public final ISession2TokensListener listener;
+ public final int userId;
+
+ Session2TokensListenerRecord(ISession2TokensListener listener,
+ int userId) {
+ this.listener = listener;
+ this.userId = userId;
+ }
+
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ mSession2TokensListenerRecords.remove(this);
+ }
+ }
+ }
+
+ final class SettingsObserver extends ContentObserver {
+ private final Uri mSecureSettingsUri = Settings.Secure.getUriFor(
+ Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+
+ private SettingsObserver() {
+ super(null);
+ }
+
+ private void observe() {
+ mContentResolver.registerContentObserver(mSecureSettingsUri,
+ false, this, USER_ALL);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ updateActiveSessionListeners();
+ }
+ }
+
+ class SessionManagerImpl extends ISessionManager.Stub {
+ private static final String EXTRA_WAKELOCK_ACQUIRED =
+ "android.media.AudioService.WAKELOCK_ACQUIRED";
+ private static final int WAKELOCK_RELEASE_ON_FINISHED = 1980; // magic number
+
+ private boolean mVoiceButtonDown = false;
+ private boolean mVoiceButtonHandled = false;
+
+ @Override
+ public ISession createSession(String packageName, ISessionCallback cb, String tag,
+ Bundle sessionInfo, int userId) throws RemoteException {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ enforcePackageName(packageName, uid);
+ int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
+ false /* allowAll */, true /* requireFull */, "createSession", packageName);
+ if (cb == null) {
+ throw new IllegalArgumentException("Controller callback cannot be null");
+ }
+ return createSessionInternal(pid, uid, resolvedUserId, packageName, cb, tag,
+ sessionInfo).getSessionBinder();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void notifySession2Created(Session2Token sessionToken) throws RemoteException {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (DEBUG) {
+ Log.d(TAG, "Session2 is created " + sessionToken);
+ }
+ if (uid != sessionToken.getUid()) {
+ throw new SecurityException("Unexpected Session2Token's UID, expected=" + uid
+ + " but actually=" + sessionToken.getUid());
+ }
+ Controller2Callback callback = new Controller2Callback(sessionToken);
+ // Note: It's safe not to keep controller here because it wouldn't be GC'ed until
+ // it's closed.
+ // TODO: Keep controller as well for better readability
+ // because the GC behavior isn't straightforward.
+ MediaController2 controller = new MediaController2.Builder(mContext, sessionToken)
+ .setControllerCallback(new HandlerExecutor(mHandler), callback)
+ .build();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public List<MediaSession.Token> getSessions(ComponentName componentName, int userId) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+
+ try {
+ int resolvedUserId = verifySessionsRequest(componentName, userId, pid, uid);
+ ArrayList<MediaSession.Token> tokens = new ArrayList<>();
+ synchronized (mLock) {
+ List<MediaSessionRecord> records = getActiveSessionsLocked(resolvedUserId);
+ for (MediaSessionRecord record : records) {
+ tokens.add(record.getSessionToken());
+ }
+ }
+ return tokens;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public ParceledListSlice getSession2Tokens(int userId) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+
+ try {
+ // Check that they can make calls on behalf of the user and
+ // get the final user id
+ int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
+ true /* allowAll */, true /* requireFull */, "getSession2Tokens",
+ null /* optional packageName */);
+ List<Session2Token> result;
+ synchronized (mLock) {
+ result = getSession2TokensLocked(resolvedUserId);
+ }
+ return new ParceledListSlice(result);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void addSessionsListener(IActiveSessionsListener listener,
+ ComponentName componentName, int userId) throws RemoteException {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+
+ try {
+ int resolvedUserId = verifySessionsRequest(componentName, userId, pid, uid);
+ synchronized (mLock) {
+ int index = findIndexOfSessionsListenerLocked(listener);
+ if (index != -1) {
+ Log.w(TAG, "ActiveSessionsListener is already added, ignoring");
+ return;
+ }
+ SessionsListenerRecord record = new SessionsListenerRecord(listener,
+ componentName, resolvedUserId, pid, uid);
+ try {
+ listener.asBinder().linkToDeath(record, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "ActiveSessionsListener is dead, ignoring it", e);
+ return;
+ }
+ mSessionsListeners.add(record);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void removeSessionsListener(IActiveSessionsListener listener)
+ throws RemoteException {
+ synchronized (mLock) {
+ int index = findIndexOfSessionsListenerLocked(listener);
+ if (index != -1) {
+ SessionsListenerRecord record = mSessionsListeners.remove(index);
+ try {
+ record.listener.asBinder().unlinkToDeath(record, 0);
+ } catch (Exception e) {
+ // ignore exceptions, the record is being removed
+ }
+ }
+ }
+ }
+
+ @Override
+ public void addSession2TokensListener(ISession2TokensListener listener,
+ int userId) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+
+ try {
+ // Check that they can make calls on behalf of the user and get the final user id.
+ int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
+ true /* allowAll */, true /* requireFull */, "addSession2TokensListener",
+ null /* optional packageName */);
+ synchronized (mLock) {
+ int index = findIndexOfSession2TokensListenerLocked(listener);
+ if (index >= 0) {
+ Log.w(TAG, "addSession2TokensListener is already added, ignoring");
+ return;
+ }
+ mSession2TokensListenerRecords.add(
+ new Session2TokensListenerRecord(listener, resolvedUserId));
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void removeSession2TokensListener(ISession2TokensListener listener) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+
+ try {
+ synchronized (mLock) {
+ int index = findIndexOfSession2TokensListenerLocked(listener);
+ if (index >= 0) {
+ Session2TokensListenerRecord listenerRecord =
+ mSession2TokensListenerRecords.remove(index);
+ try {
+ listenerRecord.listener.asBinder().unlinkToDeath(listenerRecord, 0);
+ } catch (Exception e) {
+ // Ignore exception.
+ }
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Handles the dispatching of the media button events to one of the
+ * registered listeners, or if there was none, broadcast an
+ * ACTION_MEDIA_BUTTON intent to the rest of the system.
+ *
+ * @param packageName The caller package
+ * @param asSystemService {@code true} if the event sent to the session as if it was come
+ * from the system service instead of the app process. This helps sessions to
+ * distinguish between the key injection by the app and key events from the
+ * hardware devices. Should be used only when the volume key events aren't handled
+ * by foreground activity. {@code false} otherwise to tell session about the real
+ * caller.
+ * @param keyEvent a non-null KeyEvent whose key code is one of the
+ * supported media buttons
+ * @param needWakeLock true if a PARTIAL_WAKE_LOCK needs to be held
+ * while this key event is dispatched.
+ */
+ @Override
+ public void dispatchMediaKeyEvent(String packageName, boolean asSystemService,
+ KeyEvent keyEvent, boolean needWakeLock) {
+ if (keyEvent == null || !KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())) {
+ Log.w(TAG, "Attempted to dispatch null or non-media key event.");
+ return;
+ }
+
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (DEBUG) {
+ Log.d(TAG, "dispatchMediaKeyEvent, pkg=" + packageName + " pid=" + pid
+ + ", uid=" + uid + ", asSystem=" + asSystemService + ", event="
+ + keyEvent);
+ }
+ if (!isUserSetupComplete()) {
+ // Global media key handling can have the side-effect of starting new
+ // activities which is undesirable while setup is in progress.
+ Slog.i(TAG, "Not dispatching media key event because user "
+ + "setup is in progress.");
+ return;
+ }
+
+ synchronized (mLock) {
+ boolean isGlobalPriorityActive = isGlobalPriorityActiveLocked();
+ if (isGlobalPriorityActive && uid != Process.SYSTEM_UID) {
+ // Prevent dispatching key event through reflection while the global
+ // priority session is active.
+ Slog.i(TAG, "Only the system can dispatch media key event "
+ + "to the global priority session.");
+ return;
+ }
+ if (!isGlobalPriorityActive) {
+ if (mCurrentFullUserRecord.mOnMediaKeyListener != null) {
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "Send " + keyEvent + " to the media key listener");
+ }
+ try {
+ mCurrentFullUserRecord.mOnMediaKeyListener.onMediaKey(keyEvent,
+ new MediaKeyListenerResultReceiver(packageName, pid, uid,
+ asSystemService, keyEvent, needWakeLock));
+ return;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send " + keyEvent
+ + " to the media key listener");
+ }
+ }
+ }
+ if (!isGlobalPriorityActive && isVoiceKey(keyEvent.getKeyCode())) {
+ handleVoiceKeyEventLocked(packageName, pid, uid, asSystemService, keyEvent,
+ needWakeLock);
+ } else {
+ dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
+ keyEvent, needWakeLock);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean dispatchMediaKeyEventToSessionAsSystemService(String packageName,
+ MediaSession.Token sessionToken, KeyEvent keyEvent) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
+ if (record == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Failed to find session to dispatch key event.");
+ }
+ return false;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "dispatchMediaKeyEventToSessionAsSystemService, pkg="
+ + packageName + ", pid=" + pid + ", uid=" + uid + ", sessionToken="
+ + sessionToken + ", event=" + keyEvent + ", session=" + record);
+ }
+ return record.sendMediaButton(packageName, pid, uid, true /* asSystemService */,
+ keyEvent, 0, null);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void setCallback(ICallback callback) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (!UserHandle.isSameApp(uid, Process.BLUETOOTH_UID)) {
+ throw new SecurityException("Only Bluetooth service processes can set"
+ + " Callback");
+ }
+ synchronized (mLock) {
+ int userId = UserHandle.getUserId(uid);
+ FullUserRecord user = getFullUserRecordLocked(userId);
+ if (user == null || user.mFullUserId != userId) {
+ Log.w(TAG, "Only the full user can set the callback"
+ + ", userId=" + userId);
+ return;
+ }
+ user.mCallback = callback;
+ Log.d(TAG, "The callback " + user.mCallback
+ + " is set by " + getCallingPackageName(uid));
+ if (user.mCallback == null) {
+ return;
+ }
+ try {
+ user.mCallback.asBinder().linkToDeath(
+ new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ user.mCallback = null;
+ }
+ }
+ }, 0);
+ user.pushAddressedPlayerChangedLocked();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to set callback", e);
+ user.mCallback = null;
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void setOnVolumeKeyLongPressListener(IOnVolumeKeyLongPressListener listener) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // Enforce SET_VOLUME_KEY_LONG_PRESS_LISTENER permission.
+ if (mContext.checkPermission(
+ android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER, pid, uid)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold the SET_VOLUME_KEY_LONG_PRESS_LISTENER"
+ + " permission.");
+ }
+
+ synchronized (mLock) {
+ int userId = UserHandle.getUserId(uid);
+ FullUserRecord user = getFullUserRecordLocked(userId);
+ if (user == null || user.mFullUserId != userId) {
+ Log.w(TAG, "Only the full user can set the volume key long-press listener"
+ + ", userId=" + userId);
+ return;
+ }
+ if (user.mOnVolumeKeyLongPressListener != null
+ && user.mOnVolumeKeyLongPressListenerUid != uid) {
+ Log.w(TAG, "The volume key long-press listener cannot be reset"
+ + " by another app , mOnVolumeKeyLongPressListener="
+ + user.mOnVolumeKeyLongPressListenerUid
+ + ", uid=" + uid);
+ return;
+ }
+
+ user.mOnVolumeKeyLongPressListener = listener;
+ user.mOnVolumeKeyLongPressListenerUid = uid;
+
+ Log.d(TAG, "The volume key long-press listener "
+ + listener + " is set by " + getCallingPackageName(uid));
+
+ if (user.mOnVolumeKeyLongPressListener != null) {
+ try {
+ user.mOnVolumeKeyLongPressListener.asBinder().linkToDeath(
+ new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ user.mOnVolumeKeyLongPressListener = null;
+ }
+ }
+ }, 0);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to set death recipient "
+ + user.mOnVolumeKeyLongPressListener);
+ user.mOnVolumeKeyLongPressListener = null;
+ }
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void setOnMediaKeyListener(IOnMediaKeyListener listener) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // Enforce SET_MEDIA_KEY_LISTENER permission.
+ if (mContext.checkPermission(
+ android.Manifest.permission.SET_MEDIA_KEY_LISTENER, pid, uid)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold the SET_MEDIA_KEY_LISTENER permission.");
+ }
+
+ synchronized (mLock) {
+ int userId = UserHandle.getUserId(uid);
+ FullUserRecord user = getFullUserRecordLocked(userId);
+ if (user == null || user.mFullUserId != userId) {
+ Log.w(TAG, "Only the full user can set the media key listener"
+ + ", userId=" + userId);
+ return;
+ }
+ if (user.mOnMediaKeyListener != null && user.mOnMediaKeyListenerUid != uid) {
+ Log.w(TAG, "The media key listener cannot be reset by another app. "
+ + ", mOnMediaKeyListenerUid=" + user.mOnMediaKeyListenerUid
+ + ", uid=" + uid);
+ return;
+ }
+
+ user.mOnMediaKeyListener = listener;
+ user.mOnMediaKeyListenerUid = uid;
+
+ Log.d(TAG, "The media key listener " + user.mOnMediaKeyListener
+ + " is set by " + getCallingPackageName(uid));
+
+ if (user.mOnMediaKeyListener != null) {
+ try {
+ user.mOnMediaKeyListener.asBinder().linkToDeath(
+ new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ user.mOnMediaKeyListener = null;
+ }
+ }
+ }, 0);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to set death recipient " + user.mOnMediaKeyListener);
+ user.mOnMediaKeyListener = null;
+ }
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Handles the dispatching of the volume button events to one of the
+ * registered listeners. If there's a volume key long-press listener and
+ * there's no active global priority session, long-pressess will be sent to the
+ * long-press listener instead of adjusting volume.
+ *
+ * @param packageName The caller's package name, obtained by Context#getPackageName()
+ * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName()
+ * @param asSystemService {@code true} if the event sent to the session as if it was come
+ * from the system service instead of the app process. This helps sessions to
+ * distinguish between the key injection by the app and key events from the
+ * hardware devices. Should be used only when the volume key events aren't handled
+ * by foreground activity. {@code false} otherwise to tell session about the real
+ * caller.
+ * @param keyEvent a non-null KeyEvent whose key code is one of the
+ * {@link KeyEvent#KEYCODE_VOLUME_UP},
+ * {@link KeyEvent#KEYCODE_VOLUME_DOWN},
+ * or {@link KeyEvent#KEYCODE_VOLUME_MUTE}.
+ * @param stream stream type to adjust volume.
+ * @param musicOnly true if both UI nor haptic feedback aren't needed when adjust volume.
+ */
+ @Override
+ public void dispatchVolumeKeyEvent(String packageName, String opPackageName,
+ boolean asSystemService, KeyEvent keyEvent, int stream, boolean musicOnly) {
+ if (keyEvent == null
+ || (keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_UP
+ && keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_DOWN
+ && keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_MUTE)) {
+ Log.w(TAG, "Attempted to dispatch null or non-volume key event.");
+ return;
+ }
+
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "dispatchVolumeKeyEvent, pkg=" + packageName
+ + ", opPkg=" + opPackageName + ", pid=" + pid + ", uid=" + uid
+ + ", asSystem=" + asSystemService + ", event=" + keyEvent
+ + ", stream=" + stream + ", musicOnly=" + musicOnly);
+ }
+
+ try {
+ synchronized (mLock) {
+ if (isGlobalPriorityActiveLocked()
+ || mCurrentFullUserRecord.mOnVolumeKeyLongPressListener == null) {
+ dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
+ asSystemService, keyEvent, stream, musicOnly);
+ } else {
+ // TODO: Consider the case when both volume up and down keys are pressed
+ // at the same time.
+ if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
+ if (keyEvent.getRepeatCount() == 0) {
+ // Keeps the copy of the KeyEvent because it can be reused.
+ mCurrentFullUserRecord.mInitialDownVolumeKeyEvent =
+ KeyEvent.obtain(keyEvent);
+ mCurrentFullUserRecord.mInitialDownVolumeStream = stream;
+ mCurrentFullUserRecord.mInitialDownMusicOnly = musicOnly;
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(
+ MessageHandler.MSG_VOLUME_INITIAL_DOWN,
+ mCurrentFullUserRecord.mFullUserId, 0),
+ mLongPressTimeout);
+ }
+ if (keyEvent.getRepeatCount() > 0 || keyEvent.isLongPress()) {
+ mHandler.removeMessages(MessageHandler.MSG_VOLUME_INITIAL_DOWN);
+ if (mCurrentFullUserRecord.mInitialDownVolumeKeyEvent != null) {
+ dispatchVolumeKeyLongPressLocked(
+ mCurrentFullUserRecord.mInitialDownVolumeKeyEvent);
+ // Mark that the key is already handled.
+ mCurrentFullUserRecord.mInitialDownVolumeKeyEvent = null;
+ }
+ dispatchVolumeKeyLongPressLocked(keyEvent);
+ }
+ } else { // if up
+ mHandler.removeMessages(MessageHandler.MSG_VOLUME_INITIAL_DOWN);
+ if (mCurrentFullUserRecord.mInitialDownVolumeKeyEvent != null
+ && mCurrentFullUserRecord.mInitialDownVolumeKeyEvent
+ .getDownTime() == keyEvent.getDownTime()) {
+ // Short-press. Should change volume.
+ dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
+ asSystemService,
+ mCurrentFullUserRecord.mInitialDownVolumeKeyEvent,
+ mCurrentFullUserRecord.mInitialDownVolumeStream,
+ mCurrentFullUserRecord.mInitialDownMusicOnly);
+ dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
+ asSystemService, keyEvent, stream, musicOnly);
+ } else {
+ dispatchVolumeKeyLongPressLocked(keyEvent);
+ }
+ }
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void dispatchVolumeKeyEventLocked(String packageName, String opPackageName, int pid,
+ int uid, boolean asSystemService, KeyEvent keyEvent, int stream,
+ boolean musicOnly) {
+ boolean down = keyEvent.getAction() == KeyEvent.ACTION_DOWN;
+ boolean up = keyEvent.getAction() == KeyEvent.ACTION_UP;
+ int direction = 0;
+ boolean isMute = false;
+ switch (keyEvent.getKeyCode()) {
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ direction = AudioManager.ADJUST_RAISE;
+ break;
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ direction = AudioManager.ADJUST_LOWER;
+ break;
+ case KeyEvent.KEYCODE_VOLUME_MUTE:
+ isMute = true;
+ break;
+ }
+ if (down || up) {
+ int flags = AudioManager.FLAG_FROM_KEY;
+ if (musicOnly) {
+ // This flag is used when the screen is off to only affect active media.
+ flags |= AudioManager.FLAG_ACTIVE_MEDIA_ONLY;
+ } else {
+ // These flags are consistent with the home screen
+ if (up) {
+ flags |= AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE;
+ } else {
+ flags |= AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE;
+ }
+ }
+ if (direction != 0) {
+ // If this is action up we want to send a beep for non-music events
+ if (up) {
+ direction = 0;
+ }
+ dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid,
+ asSystemService, stream, direction, flags);
+ } else if (isMute) {
+ if (down && keyEvent.getRepeatCount() == 0) {
+ dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid,
+ asSystemService, stream, AudioManager.ADJUST_TOGGLE_MUTE, flags);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void dispatchVolumeKeyEventToSessionAsSystemService(String packageName,
+ String opPackageName, MediaSession.Token sessionToken, KeyEvent keyEvent) {
+ int pid = Binder.getCallingPid();
+ int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
+ if (record == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Failed to find session to dispatch key event.");
+ }
+ return;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "dispatchVolumeKeyEventToSessionAsSystemService, pkg="
+ + packageName + ", opPkg=" + opPackageName + ", pid=" + pid
+ + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event="
+ + keyEvent + ", session=" + record);
+ }
+ switch (keyEvent.getAction()) {
+ case KeyEvent.ACTION_DOWN: {
+ int direction = 0;
+ switch (keyEvent.getKeyCode()) {
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ direction = AudioManager.ADJUST_RAISE;
+ break;
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ direction = AudioManager.ADJUST_LOWER;
+ break;
+ case KeyEvent.KEYCODE_VOLUME_MUTE:
+ direction = AudioManager.ADJUST_TOGGLE_MUTE;
+ break;
+ }
+ record.adjustVolume(packageName, opPackageName, pid, uid,
+ null /* caller */, true /* asSystemService */, direction,
+ AudioManager.FLAG_SHOW_UI, false /* useSuggested */);
+ break;
+ }
+
+ case KeyEvent.ACTION_UP: {
+ final int flags =
+ AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
+ | AudioManager.FLAG_FROM_KEY;
+ record.adjustVolume(packageName, opPackageName, pid, uid,
+ null /* caller */, true /* asSystemService */, 0,
+ flags, false /* useSuggested */);
+ }
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void dispatchAdjustVolume(String packageName, String opPackageName,
+ int suggestedStream, int delta, int flags) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid, false,
+ suggestedStream, delta, flags);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void registerRemoteVolumeController(IRemoteVolumeController rvc) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ synchronized (mLock) {
+ try {
+ enforceStatusBarServicePermission("listen for volume changes", pid, uid);
+ mRemoteVolumeControllers.register(rvc);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ @Override
+ public void unregisterRemoteVolumeController(IRemoteVolumeController rvc) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ synchronized (mLock) {
+ try {
+ enforceStatusBarServicePermission("listen for volume changes", pid, uid);
+ mRemoteVolumeControllers.unregister(rvc);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ @Override
+ public boolean isGlobalPriorityActive() {
+ synchronized (mLock) {
+ return isGlobalPriorityActiveLocked();
+ }
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+
+ pw.println("MEDIA SESSION SERVICE (dumpsys media_session)");
+ pw.println();
+
+ synchronized (mLock) {
+ pw.println(mSessionsListeners.size() + " sessions listeners.");
+ pw.println("Global priority session is " + mGlobalPrioritySession);
+ if (mGlobalPrioritySession != null) {
+ mGlobalPrioritySession.dump(pw, " ");
+ }
+ pw.println("User Records:");
+ int count = mUserRecords.size();
+ for (int i = 0; i < count; i++) {
+ mUserRecords.valueAt(i).dumpLocked(pw, "");
+ }
+ mAudioPlayerStateMonitor.dump(mContext, pw, "");
+ }
+ }
+
+ /**
+ * Returns if the controller's package is trusted (i.e. has either MEDIA_CONTENT_CONTROL
+ * permission or an enabled notification listener)
+ *
+ * @param controllerPackageName package name of the controller app
+ * @param controllerPid pid of the controller app
+ * @param controllerUid uid of the controller app
+ */
+ @Override
+ public boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid)
+ throws RemoteException {
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // Don't perform sanity check between controllerPackageName and controllerUid.
+ // When an (activity|service) runs on the another apps process by specifying
+ // android:process in the AndroidManifest.xml, then PID and UID would have the
+ // running process' information instead of the (activity|service) that has created
+ // MediaController.
+ // Note that we can use Context#getOpPackageName() instead of
+ // Context#getPackageName() for getting package name that matches with the PID/UID,
+ // but it doesn't tell which package has created the MediaController, so useless.
+ return hasMediaControlPermission(UserHandle.getUserId(uid), controllerPackageName,
+ controllerPid, controllerUid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ // For MediaSession
+ private int verifySessionsRequest(ComponentName componentName, int userId, final int pid,
+ final int uid) {
+ String packageName = null;
+ if (componentName != null) {
+ // If they gave us a component name verify they own the
+ // package
+ packageName = componentName.getPackageName();
+ enforcePackageName(packageName, uid);
+ }
+ // Check that they can make calls on behalf of the user and
+ // get the final user id
+ int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
+ true /* allowAll */, true /* requireFull */, "getSessions", packageName);
+ // Check if they have the permissions or their component is
+ // enabled for the user they're calling from.
+ enforceMediaPermissions(componentName, pid, uid, resolvedUserId);
+ return resolvedUserId;
+ }
+
+ private boolean hasMediaControlPermission(int resolvedUserId, String packageName,
+ int pid, int uid) throws RemoteException {
+ // Allow API calls from the System UI and Settings
+ if (hasStatusBarServicePermission(pid, uid)) {
+ return true;
+ }
+
+ // Check if it's system server or has MEDIA_CONTENT_CONTROL.
+ // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
+ // check here.
+ if (uid == Process.SYSTEM_UID || mContext.checkPermission(
+ android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
+ == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ } else if (DEBUG) {
+ Log.d(TAG, packageName + " (uid=" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
+ }
+
+ // You may not access another user's content as an enabled listener.
+ final int userId = UserHandle.getUserId(uid);
+ if (resolvedUserId != userId) {
+ return false;
+ }
+
+ // TODO(jaewan): (Post-P) Propose NotificationManager#hasEnabledNotificationListener(
+ // String pkgName) to notification team for optimization
+ final List<ComponentName> enabledNotificationListeners =
+ mNotificationManager.getEnabledNotificationListeners(userId);
+ if (enabledNotificationListeners != null) {
+ for (int i = 0; i < enabledNotificationListeners.size(); i++) {
+ if (TextUtils.equals(packageName,
+ enabledNotificationListeners.get(i).getPackageName())) {
+ return true;
+ }
+ }
+ }
+ if (DEBUG) {
+ Log.d(TAG, packageName + " (uid=" + uid + ") doesn't have an enabled "
+ + "notification listener");
+ }
+ return false;
+ }
+
+ private void dispatchAdjustVolumeLocked(String packageName, String opPackageName, int pid,
+ int uid, boolean asSystemService, int suggestedStream, int direction, int flags) {
+ MediaSessionRecord session = isGlobalPriorityActiveLocked() ? mGlobalPrioritySession
+ : mCurrentFullUserRecord.mPriorityStack.getDefaultVolumeSession();
+
+ boolean preferSuggestedStream = false;
+ if (isValidLocalStreamType(suggestedStream)
+ && AudioSystem.isStreamActive(suggestedStream, 0)) {
+ preferSuggestedStream = true;
+ }
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "Adjusting " + session + " by " + direction + ". flags="
+ + flags + ", suggestedStream=" + suggestedStream
+ + ", preferSuggestedStream=" + preferSuggestedStream);
+ }
+ if (session == null || preferSuggestedStream) {
+ if ((flags & AudioManager.FLAG_ACTIVE_MEDIA_ONLY) != 0
+ && !AudioSystem.isStreamActive(AudioManager.STREAM_MUSIC, 0)) {
+ if (DEBUG) {
+ Log.d(TAG, "No active session to adjust, skipping media only volume event");
+ }
+ return;
+ }
+
+ // Execute mAudioService.adjustSuggestedStreamVolume() on
+ // handler thread of MediaSessionService.
+ // This will release the MediaSessionService.mLock sooner and avoid
+ // a potential deadlock between MediaSessionService.mLock and
+ // ActivityManagerService lock.
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ final String callingOpPackageName;
+ final int callingUid;
+ if (asSystemService) {
+ callingOpPackageName = mContext.getOpPackageName();
+ callingUid = Process.myUid();
+ } else {
+ callingOpPackageName = opPackageName;
+ callingUid = uid;
+ }
+ try {
+ mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(suggestedStream,
+ direction, flags, callingOpPackageName, callingUid);
+ } catch (SecurityException | IllegalArgumentException e) {
+ Log.e(TAG, "Cannot adjust volume: direction=" + direction
+ + ", suggestedStream=" + suggestedStream + ", flags=" + flags
+ + ", packageName=" + packageName + ", uid=" + uid
+ + ", asSystemService=" + asSystemService, e);
+ }
+ }
+ });
+ } else {
+ session.adjustVolume(packageName, opPackageName, pid, uid, null, asSystemService,
+ direction, flags, true);
+ }
+ }
+
+ private void handleVoiceKeyEventLocked(String packageName, int pid, int uid,
+ boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
+ int action = keyEvent.getAction();
+ boolean isLongPress = (keyEvent.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0;
+ if (action == KeyEvent.ACTION_DOWN) {
+ if (keyEvent.getRepeatCount() == 0) {
+ mVoiceButtonDown = true;
+ mVoiceButtonHandled = false;
+ } else if (mVoiceButtonDown && !mVoiceButtonHandled && isLongPress) {
+ mVoiceButtonHandled = true;
+ startVoiceInput(needWakeLock);
+ }
+ } else if (action == KeyEvent.ACTION_UP) {
+ if (mVoiceButtonDown) {
+ mVoiceButtonDown = false;
+ if (!mVoiceButtonHandled && !keyEvent.isCanceled()) {
+ // Resend the down then send this event through
+ KeyEvent downEvent = KeyEvent.changeAction(keyEvent, KeyEvent.ACTION_DOWN);
+ dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
+ downEvent, needWakeLock);
+ dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
+ keyEvent, needWakeLock);
+ }
+ }
+ }
+ }
+
+ private void dispatchMediaKeyEventLocked(String packageName, int pid, int uid,
+ boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
+ MediaSessionRecord session = mCurrentFullUserRecord.getMediaButtonSessionLocked();
+ if (session != null) {
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "Sending " + keyEvent + " to " + session);
+ }
+ if (needWakeLock) {
+ mKeyEventReceiver.aquireWakeLockLocked();
+ }
+ // If we don't need a wakelock use -1 as the id so we won't release it later.
+ session.sendMediaButton(packageName, pid, uid, asSystemService, keyEvent,
+ needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
+ mKeyEventReceiver);
+ if (mCurrentFullUserRecord.mCallback != null) {
+ try {
+ mCurrentFullUserRecord.mCallback.onMediaKeyEventDispatchedToMediaSession(
+ keyEvent, session.getSessionToken());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send callback", e);
+ }
+ }
+ } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null
+ || mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
+ if (needWakeLock) {
+ mKeyEventReceiver.aquireWakeLockLocked();
+ }
+ Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+ mediaButtonIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+ // TODO: Find a way to also send PID/UID in secure way.
+ String callerPackageName =
+ (asSystemService) ? mContext.getPackageName() : packageName;
+ mediaButtonIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, callerPackageName);
+ try {
+ if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
+ PendingIntent receiver = mCurrentFullUserRecord.mLastMediaButtonReceiver;
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "Sending " + keyEvent
+ + " to the last known PendingIntent " + receiver);
+ }
+ receiver.send(mContext,
+ needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
+ mediaButtonIntent, mKeyEventReceiver, mHandler);
+ if (mCurrentFullUserRecord.mCallback != null) {
+ ComponentName componentName = mCurrentFullUserRecord
+ .mLastMediaButtonReceiver.getIntent().getComponent();
+ if (componentName != null) {
+ mCurrentFullUserRecord.mCallback
+ .onMediaKeyEventDispatchedToMediaButtonReceiver(
+ keyEvent, componentName);
+ }
+ }
+ } else {
+ ComponentName receiver =
+ mCurrentFullUserRecord.mRestoredMediaButtonReceiver;
+ int componentType = mCurrentFullUserRecord
+ .mRestoredMediaButtonReceiverComponentType;
+ UserHandle userHandle = UserHandle.of(mCurrentFullUserRecord
+ .mRestoredMediaButtonReceiverUserId);
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "Sending " + keyEvent + " to the restored intent "
+ + receiver + ", type=" + componentType);
+ }
+ mediaButtonIntent.setComponent(receiver);
+ try {
+ switch (componentType) {
+ case FullUserRecord.COMPONENT_TYPE_ACTIVITY:
+ mContext.startActivityAsUser(mediaButtonIntent, userHandle);
+ break;
+ case FullUserRecord.COMPONENT_TYPE_SERVICE:
+ mContext.startForegroundServiceAsUser(mediaButtonIntent,
+ userHandle);
+ break;
+ default:
+ // Legacy behavior for other cases.
+ mContext.sendBroadcastAsUser(mediaButtonIntent, userHandle);
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "Error sending media button to the restored intent "
+ + receiver + ", type=" + componentType, e);
+ }
+ if (mCurrentFullUserRecord.mCallback != null) {
+ mCurrentFullUserRecord.mCallback
+ .onMediaKeyEventDispatchedToMediaButtonReceiver(
+ keyEvent, receiver);
+ }
+ }
+ } catch (CanceledException e) {
+ Log.i(TAG, "Error sending key event to media button receiver "
+ + mCurrentFullUserRecord.mLastMediaButtonReceiver, e);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send callback", e);
+ }
+ }
+ }
+
+ private void startVoiceInput(boolean needWakeLock) {
+ Intent voiceIntent = null;
+ // select which type of search to launch:
+ // - screen on and device unlocked: action is ACTION_WEB_SEARCH
+ // - device locked or screen off: action is
+ // ACTION_VOICE_SEARCH_HANDS_FREE
+ // with EXTRA_SECURE set to true if the device is securely locked
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ boolean isLocked = mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
+ if (!isLocked && pm.isScreenOn()) {
+ voiceIntent = new Intent(android.speech.RecognizerIntent.ACTION_WEB_SEARCH);
+ Log.i(TAG, "voice-based interactions: about to use ACTION_WEB_SEARCH");
+ } else {
+ voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
+ voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE,
+ isLocked && mKeyguardManager.isKeyguardSecure());
+ Log.i(TAG, "voice-based interactions: about to use ACTION_VOICE_SEARCH_HANDS_FREE");
+ }
+ // start the search activity
+ if (needWakeLock) {
+ mMediaEventWakeLock.acquire();
+ }
+ try {
+ if (voiceIntent != null) {
+ voiceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ if (DEBUG) Log.d(TAG, "voiceIntent: " + voiceIntent);
+ mContext.startActivityAsUser(voiceIntent, UserHandle.CURRENT);
+ }
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "No activity for search: " + e);
+ } finally {
+ if (needWakeLock) {
+ mMediaEventWakeLock.release();
+ }
+ }
+ }
+
+ private boolean isVoiceKey(int keyCode) {
+ return keyCode == KeyEvent.KEYCODE_HEADSETHOOK
+ || (!mHasFeatureLeanback && keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+ }
+
+ private boolean isUserSetupComplete() {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
+ }
+
+ // we only handle public stream types, which are 0-5
+ private boolean isValidLocalStreamType(int streamType) {
+ return streamType >= AudioManager.STREAM_VOICE_CALL
+ && streamType <= AudioManager.STREAM_NOTIFICATION;
+ }
+
+ private class MediaKeyListenerResultReceiver extends ResultReceiver implements Runnable {
+ private final String mPackageName;
+ private final int mPid;
+ private final int mUid;
+ private final boolean mAsSystemService;
+ private final KeyEvent mKeyEvent;
+ private final boolean mNeedWakeLock;
+ private boolean mHandled;
+
+ private MediaKeyListenerResultReceiver(String packageName, int pid, int uid,
+ boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
+ super(mHandler);
+ mHandler.postDelayed(this, MEDIA_KEY_LISTENER_TIMEOUT);
+ mPackageName = packageName;
+ mPid = pid;
+ mUid = uid;
+ mAsSystemService = asSystemService;
+ mKeyEvent = keyEvent;
+ mNeedWakeLock = needWakeLock;
+ }
+
+ @Override
+ public void run() {
+ Log.d(TAG, "The media key listener is timed-out for " + mKeyEvent);
+ dispatchMediaKeyEvent();
+ }
+
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (resultCode == MediaSessionManager.RESULT_MEDIA_KEY_HANDLED) {
+ mHandled = true;
+ mHandler.removeCallbacks(this);
+ return;
+ }
+ dispatchMediaKeyEvent();
+ }
+
+ private void dispatchMediaKeyEvent() {
+ if (mHandled) {
+ return;
+ }
+ mHandled = true;
+ mHandler.removeCallbacks(this);
+ synchronized (mLock) {
+ if (!isGlobalPriorityActiveLocked()
+ && isVoiceKey(mKeyEvent.getKeyCode())) {
+ handleVoiceKeyEventLocked(mPackageName, mPid, mUid, mAsSystemService,
+ mKeyEvent, mNeedWakeLock);
+ } else {
+ dispatchMediaKeyEventLocked(mPackageName, mPid, mUid, mAsSystemService,
+ mKeyEvent, mNeedWakeLock);
+ }
+ }
+ }
+ }
+
+ private KeyEventWakeLockReceiver mKeyEventReceiver = new KeyEventWakeLockReceiver(mHandler);
+
+ class KeyEventWakeLockReceiver extends ResultReceiver implements Runnable,
+ PendingIntent.OnFinished {
+ private final Handler mHandler;
+ private int mRefCount = 0;
+ private int mLastTimeoutId = 0;
+
+ KeyEventWakeLockReceiver(Handler handler) {
+ super(handler);
+ mHandler = handler;
+ }
+
+ public void onTimeout() {
+ synchronized (mLock) {
+ if (mRefCount == 0) {
+ // We've already released it, so just return
+ return;
+ }
+ mLastTimeoutId++;
+ mRefCount = 0;
+ releaseWakeLockLocked();
+ }
+ }
+
+ public void aquireWakeLockLocked() {
+ if (mRefCount == 0) {
+ mMediaEventWakeLock.acquire();
+ }
+ mRefCount++;
+ mHandler.removeCallbacks(this);
+ mHandler.postDelayed(this, WAKELOCK_TIMEOUT);
+
+ }
+
+ @Override
+ public void run() {
+ onTimeout();
+ }
+
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (resultCode < mLastTimeoutId) {
+ // Ignore results from calls that were before the last
+ // timeout, just in case.
+ return;
+ } else {
+ synchronized (mLock) {
+ if (mRefCount > 0) {
+ mRefCount--;
+ if (mRefCount == 0) {
+ releaseWakeLockLocked();
+ }
+ }
+ }
+ }
+ }
+
+ private void releaseWakeLockLocked() {
+ mMediaEventWakeLock.release();
+ mHandler.removeCallbacks(this);
+ }
+
+ @Override
+ public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
+ String resultData, Bundle resultExtras) {
+ onReceiveResult(resultCode, null);
+ }
+ };
+
+ BroadcastReceiver mKeyEventDone = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent == null) {
+ return;
+ }
+ Bundle extras = intent.getExtras();
+ if (extras == null) {
+ return;
+ }
+ synchronized (mLock) {
+ if (extras.containsKey(EXTRA_WAKELOCK_ACQUIRED)
+ && mMediaEventWakeLock.isHeld()) {
+ mMediaEventWakeLock.release();
+ }
+ }
+ }
+ };
+ }
+
+ final class MessageHandler extends Handler {
+ private static final int MSG_SESSIONS_CHANGED = 1;
+ private static final int MSG_VOLUME_INITIAL_DOWN = 2;
+ private final SparseArray<Integer> mIntegerCache = new SparseArray<>();
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_SESSIONS_CHANGED:
+ pushSessionsChanged((int) msg.obj);
+ break;
+ case MSG_VOLUME_INITIAL_DOWN:
+ synchronized (mLock) {
+ FullUserRecord user = mUserRecords.get((int) msg.arg1);
+ if (user != null && user.mInitialDownVolumeKeyEvent != null) {
+ dispatchVolumeKeyLongPressLocked(user.mInitialDownVolumeKeyEvent);
+ // Mark that the key is already handled.
+ user.mInitialDownVolumeKeyEvent = null;
+ }
+ }
+ break;
+ }
+ }
+
+ public void postSessionsChanged(int userId) {
+ // Use object instead of the arguments when posting message to remove pending requests.
+ Integer userIdInteger = mIntegerCache.get(userId);
+ if (userIdInteger == null) {
+ userIdInteger = Integer.valueOf(userId);
+ mIntegerCache.put(userId, userIdInteger);
+ }
+ removeMessages(MSG_SESSIONS_CHANGED, userIdInteger);
+ obtainMessage(MSG_SESSIONS_CHANGED, userIdInteger).sendToTarget();
+ }
+ }
+
+ private class Controller2Callback extends MediaController2.ControllerCallback {
+ private final Session2Token mToken;
+
+ Controller2Callback(Session2Token token) {
+ mToken = token;
+ }
+
+ @Override
+ public void onConnected(MediaController2 controller, Session2CommandGroup allowedCommands) {
+ synchronized (mLock) {
+ int userId = UserHandle.getUserId(mToken.getUid());
+ mSession2TokensPerUser.get(userId).add(mToken);
+ pushSession2TokensChangedLocked(userId);
+ }
+ }
+
+ @Override
+ public void onDisconnected(MediaController2 controller) {
+ synchronized (mLock) {
+ int userId = UserHandle.getUserId(mToken.getUid());
+ mSession2TokensPerUser.get(userId).remove(mToken);
+ pushSession2TokensChangedLocked(userId);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
deleted file mode 100644
index aa886c2..0000000
--- a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
+++ /dev/null
@@ -1,2274 +0,0 @@
-/*
- * Copyright 2019 The Android Open 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.media;
-
-import static android.os.UserHandle.USER_ALL;
-
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.INotificationManager;
-import android.app.KeyguardManager;
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.content.ActivityNotFoundException;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ParceledListSlice;
-import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
-import android.database.ContentObserver;
-import android.media.AudioManager;
-import android.media.AudioManagerInternal;
-import android.media.AudioPlaybackConfiguration;
-import android.media.AudioSystem;
-import android.media.IAudioService;
-import android.media.IRemoteVolumeController;
-import android.media.MediaController2;
-import android.media.Session2CommandGroup;
-import android.media.Session2Token;
-import android.media.session.IActiveSessionsListener;
-import android.media.session.ICallback;
-import android.media.session.IOnMediaKeyListener;
-import android.media.session.IOnVolumeKeyLongPressListener;
-import android.media.session.ISession;
-import android.media.session.ISession2TokensListener;
-import android.media.session.ISessionCallback;
-import android.media.session.ISessionManager;
-import android.media.session.MediaSession;
-import android.media.session.MediaSessionManager;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerExecutor;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.Process;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.speech.RecognizerIntent;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
-import android.view.KeyEvent;
-import android.view.ViewConfiguration;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.DumpUtils;
-import com.android.server.LocalServices;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * System implementation of MediaSessionManager
- */
-public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
- private static final String TAG = "MediaSessionService";
- static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- // Leave log for key event always.
- private static final boolean DEBUG_KEY_EVENT = true;
-
- private static final int WAKELOCK_TIMEOUT = 5000;
- private static final int MEDIA_KEY_LISTENER_TIMEOUT = 1000;
-
- private final Context mContext;
- private final SessionManagerImpl mSessionManagerImpl;
- private final MessageHandler mHandler = new MessageHandler();
- private final PowerManager.WakeLock mMediaEventWakeLock;
- private final int mLongPressTimeout;
- private final INotificationManager mNotificationManager;
- private final Object mLock = new Object();
- // Keeps the full user id for each user.
- @GuardedBy("mLock")
- private final SparseIntArray mFullUserIds = new SparseIntArray();
- @GuardedBy("mLock")
- private final SparseArray<FullUserRecord> mUserRecords = new SparseArray<FullUserRecord>();
- @GuardedBy("mLock")
- private final ArrayList<SessionsListenerRecord> mSessionsListeners =
- new ArrayList<SessionsListenerRecord>();
- // Map user id as index to list of Session2Tokens
- // TODO: Keep session2 info in MediaSessionStack for prioritizing both session1 and session2 in
- // one place.
- @GuardedBy("mLock")
- private final SparseArray<List<Session2Token>> mSession2TokensPerUser = new SparseArray<>();
- @GuardedBy("mLock")
- private final List<Session2TokensListenerRecord> mSession2TokensListenerRecords =
- new ArrayList<>();
-
- private KeyguardManager mKeyguardManager;
- private IAudioService mAudioService;
- private AudioManagerInternal mAudioManagerInternal;
- private ActivityManager mActivityManager;
- private ContentResolver mContentResolver;
- private SettingsObserver mSettingsObserver;
- private boolean mHasFeatureLeanback;
-
- // The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile)
- // It's always not null after the MediaSessionService is started.
- private FullUserRecord mCurrentFullUserRecord;
- private MediaSessionRecord mGlobalPrioritySession;
- private AudioPlayerStateMonitor mAudioPlayerStateMonitor;
-
- // Used to notify System UI and Settings when remote volume was changed.
- @GuardedBy("mLock")
- final RemoteCallbackList<IRemoteVolumeController> mRemoteVolumeControllers =
- new RemoteCallbackList<>();
-
- public MediaSessionServiceImpl(Context context) {
- mContext = context;
- mSessionManagerImpl = new SessionManagerImpl();
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent");
- mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
- mNotificationManager = INotificationManager.Stub.asInterface(
- ServiceManager.getService(Context.NOTIFICATION_SERVICE));
- }
-
- Context getContext() {
- return mContext;
- }
-
- IBinder getServiceBinder() {
- return mSessionManagerImpl;
- }
-
- @Override
- public void onStart() {
- mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
- mAudioService = getAudioService();
- mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
- mActivityManager =
- (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(mContext);
- mAudioPlayerStateMonitor.registerListener(
- (config, isRemoved) -> {
- if (config.getPlayerType()
- == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
- return;
- }
- synchronized (mLock) {
- FullUserRecord user = getFullUserRecordLocked(
- UserHandle.getUserId(config.getClientUid()));
- if (user != null) {
- user.mPriorityStack.updateMediaButtonSessionIfNeeded();
- }
- }
- }, null /* handler */);
- mContentResolver = mContext.getContentResolver();
- mSettingsObserver = new SettingsObserver();
- mSettingsObserver.observe();
- mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_LEANBACK);
-
- updateUser();
- }
-
- private IAudioService getAudioService() {
- IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
- return IAudioService.Stub.asInterface(b);
- }
-
- private boolean isGlobalPriorityActiveLocked() {
- return mGlobalPrioritySession != null && mGlobalPrioritySession.isActive();
- }
-
- @Override
- public void updateSession(MediaSessionRecord record) {
- synchronized (mLock) {
- FullUserRecord user = getFullUserRecordLocked(record.getUserId());
- if (user == null) {
- Log.w(TAG, "Unknown session updated. Ignoring.");
- return;
- }
- if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
- if (DEBUG_KEY_EVENT) {
- Log.d(TAG, "Global priority session is updated, active=" + record.isActive());
- }
- user.pushAddressedPlayerChangedLocked();
- } else {
- if (!user.mPriorityStack.contains(record)) {
- Log.w(TAG, "Unknown session updated. Ignoring.");
- return;
- }
- user.mPriorityStack.onSessionStateChange(record);
- }
- mHandler.postSessionsChanged(record.getUserId());
- }
- }
-
- @Override
- public void setGlobalPrioritySession(MediaSessionRecord record) {
- synchronized (mLock) {
- FullUserRecord user = getFullUserRecordLocked(record.getUserId());
- if (mGlobalPrioritySession != record) {
- Log.d(TAG, "Global priority session is changed from " + mGlobalPrioritySession
- + " to " + record);
- mGlobalPrioritySession = record;
- if (user != null && user.mPriorityStack.contains(record)) {
- // Handle the global priority session separately.
- // Otherwise, it can be the media button session regardless of the active state
- // because it or other system components might have been the lastly played media
- // app.
- user.mPriorityStack.removeSession(record);
- }
- }
- }
- }
-
- private List<MediaSessionRecord> getActiveSessionsLocked(int userId) {
- List<MediaSessionRecord> records = new ArrayList<>();
- if (userId == USER_ALL) {
- int size = mUserRecords.size();
- for (int i = 0; i < size; i++) {
- records.addAll(mUserRecords.valueAt(i).mPriorityStack.getActiveSessions(userId));
- }
- } else {
- FullUserRecord user = getFullUserRecordLocked(userId);
- if (user == null) {
- Log.w(TAG, "getSessions failed. Unknown user " + userId);
- return records;
- }
- records.addAll(user.mPriorityStack.getActiveSessions(userId));
- }
-
- // Return global priority session at the first whenever it's asked.
- if (isGlobalPriorityActiveLocked()
- && (userId == USER_ALL || userId == mGlobalPrioritySession.getUserId())) {
- records.add(0, mGlobalPrioritySession);
- }
- return records;
- }
-
- List<Session2Token> getSession2TokensLocked(int userId) {
- List<Session2Token> list = new ArrayList<>();
- if (userId == USER_ALL) {
- for (int i = 0; i < mSession2TokensPerUser.size(); i++) {
- list.addAll(mSession2TokensPerUser.valueAt(i));
- }
- } else {
- list.addAll(mSession2TokensPerUser.get(userId));
- }
- return list;
- }
-
- /**
- * Tells the System UI and Settings app that volume has changed on an active remote session.
- */
- public void notifyRemoteVolumeChanged(int flags, MediaSessionRecord session) {
- if (!session.isActive()) {
- return;
- }
- synchronized (mLock) {
- int size = mRemoteVolumeControllers.beginBroadcast();
- MediaSession.Token token = session.getSessionToken();
- for (int i = size - 1; i >= 0; i--) {
- try {
- IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
- cb.remoteVolumeChanged(token, flags);
- } catch (Exception e) {
- Log.w(TAG, "Error sending volume change.", e);
- }
- }
- mRemoteVolumeControllers.finishBroadcast();
- }
- }
-
- @Override
- public void onSessionPlaystateChanged(MediaSessionRecord record, int oldState, int newState) {
- synchronized (mLock) {
- FullUserRecord user = getFullUserRecordLocked(record.getUserId());
- if (user == null || !user.mPriorityStack.contains(record)) {
- Log.d(TAG, "Unknown session changed playback state. Ignoring.");
- return;
- }
- user.mPriorityStack.onPlaystateChanged(record, oldState, newState);
- }
- }
-
- @Override
- public void onSessionPlaybackTypeChanged(MediaSessionRecord record) {
- synchronized (mLock) {
- FullUserRecord user = getFullUserRecordLocked(record.getUserId());
- if (user == null || !user.mPriorityStack.contains(record)) {
- Log.d(TAG, "Unknown session changed playback type. Ignoring.");
- return;
- }
- pushRemoteVolumeUpdateLocked(record.getUserId());
- }
- }
-
- @Override
- public void onStartUser(int userId) {
- if (DEBUG) Log.d(TAG, "onStartUser: " + userId);
- updateUser();
- }
-
- @Override
- public void onSwitchUser(int userId) {
- if (DEBUG) Log.d(TAG, "onSwitchUser: " + userId);
- updateUser();
- }
-
- // Called when the user with the userId is removed.
- @Override
- public void onStopUser(int userId) {
- if (DEBUG) Log.d(TAG, "onStopUser: " + userId);
- synchronized (mLock) {
- // TODO: Also handle removing user in updateUser() because adding/switching user is
- // handled in updateUser().
- FullUserRecord user = getFullUserRecordLocked(userId);
- if (user != null) {
- if (user.mFullUserId == userId) {
- user.destroySessionsForUserLocked(USER_ALL);
- mUserRecords.remove(userId);
- } else {
- user.destroySessionsForUserLocked(userId);
- }
- }
- mSession2TokensPerUser.remove(userId);
- updateUser();
- }
- }
-
- @Override
- public void monitor() {
- synchronized (mLock) {
- // Check for deadlock
- }
- }
-
- protected void enforcePhoneStatePermission(int pid, int uid) {
- if (mContext.checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE, pid, uid)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold the MODIFY_PHONE_STATE permission.");
- }
- }
-
- void sessionDied(MediaSessionRecord session) {
- synchronized (mLock) {
- destroySessionLocked(session);
- }
- }
-
- void destroySession(MediaSessionRecord session) {
- synchronized (mLock) {
- destroySessionLocked(session);
- }
- }
-
- private void updateUser() {
- synchronized (mLock) {
- UserManager manager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- mFullUserIds.clear();
- List<UserInfo> allUsers = manager.getUsers();
- if (allUsers != null) {
- for (UserInfo userInfo : allUsers) {
- if (userInfo.isManagedProfile()) {
- mFullUserIds.put(userInfo.id, userInfo.profileGroupId);
- } else {
- mFullUserIds.put(userInfo.id, userInfo.id);
- if (mUserRecords.get(userInfo.id) == null) {
- mUserRecords.put(userInfo.id, new FullUserRecord(userInfo.id));
- }
- }
- if (mSession2TokensPerUser.get(userInfo.id) == null) {
- mSession2TokensPerUser.put(userInfo.id, new ArrayList<>());
- }
- }
- }
- // Ensure that the current full user exists.
- int currentFullUserId = ActivityManager.getCurrentUser();
- mCurrentFullUserRecord = mUserRecords.get(currentFullUserId);
- if (mCurrentFullUserRecord == null) {
- Log.w(TAG, "Cannot find FullUserInfo for the current user " + currentFullUserId);
- mCurrentFullUserRecord = new FullUserRecord(currentFullUserId);
- mUserRecords.put(currentFullUserId, mCurrentFullUserRecord);
- if (mSession2TokensPerUser.get(currentFullUserId) == null) {
- mSession2TokensPerUser.put(currentFullUserId, new ArrayList<>());
- }
- }
- mFullUserIds.put(currentFullUserId, currentFullUserId);
- }
- }
-
- private void updateActiveSessionListeners() {
- synchronized (mLock) {
- for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
- SessionsListenerRecord listener = mSessionsListeners.get(i);
- try {
- enforceMediaPermissions(listener.componentName, listener.pid, listener.uid,
- listener.userId);
- } catch (SecurityException e) {
- Log.i(TAG, "ActiveSessionsListener " + listener.componentName
- + " is no longer authorized. Disconnecting.");
- mSessionsListeners.remove(i);
- try {
- listener.listener
- .onActiveSessionsChanged(new ArrayList<MediaSession.Token>());
- } catch (Exception e1) {
- // ignore
- }
- }
- }
- }
- }
-
- /*
- * When a session is removed several things need to happen.
- * 1. We need to remove it from the relevant user.
- * 2. We need to remove it from the priority stack.
- * 3. We need to remove it from all sessions.
- * 4. If this is the system priority session we need to clear it.
- * 5. We need to unlink to death from the cb binder
- * 6. We need to tell the session to do any final cleanup (onDestroy)
- */
- private void destroySessionLocked(MediaSessionRecord session) {
- if (DEBUG) {
- Log.d(TAG, "Destroying " + session);
- }
- FullUserRecord user = getFullUserRecordLocked(session.getUserId());
- if (mGlobalPrioritySession == session) {
- mGlobalPrioritySession = null;
- if (session.isActive() && user != null) {
- user.pushAddressedPlayerChangedLocked();
- }
- } else {
- if (user != null) {
- user.mPriorityStack.removeSession(session);
- }
- }
-
- try {
- session.getCallback().asBinder().unlinkToDeath(session, 0);
- } catch (Exception e) {
- // ignore exceptions while destroying a session.
- }
- session.onDestroy();
- mHandler.postSessionsChanged(session.getUserId());
- }
-
- private void enforcePackageName(String packageName, int uid) {
- if (TextUtils.isEmpty(packageName)) {
- throw new IllegalArgumentException("packageName may not be empty");
- }
- String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
- final int packageCount = packages.length;
- for (int i = 0; i < packageCount; i++) {
- if (packageName.equals(packages[i])) {
- return;
- }
- }
- throw new IllegalArgumentException("packageName is not owned by the calling process");
- }
-
- /**
- * Checks a caller's authorization to register an IRemoteControlDisplay.
- * Authorization is granted if one of the following is true:
- * <ul>
- * <li>the caller has android.Manifest.permission.MEDIA_CONTENT_CONTROL
- * permission</li>
- * <li>the caller's listener is one of the enabled notification listeners
- * for the caller's user</li>
- * </ul>
- */
- private void enforceMediaPermissions(ComponentName compName, int pid, int uid,
- int resolvedUserId) {
- if (hasStatusBarServicePermission(pid, uid)) return;
- if (mContext
- .checkPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
- != PackageManager.PERMISSION_GRANTED
- && !isEnabledNotificationListener(compName, UserHandle.getUserId(uid),
- resolvedUserId)) {
- throw new SecurityException("Missing permission to control media.");
- }
- }
-
- private boolean hasStatusBarServicePermission(int pid, int uid) {
- return mContext.checkPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
- pid, uid) == PackageManager.PERMISSION_GRANTED;
- }
-
- private void enforceStatusBarServicePermission(String action, int pid, int uid) {
- if (!hasStatusBarServicePermission(pid, uid)) {
- throw new SecurityException("Only System UI and Settings may " + action);
- }
- }
-
- /**
- * This checks if the component is an enabled notification listener for the
- * specified user. Enabled components may only operate on behalf of the user
- * they're running as.
- *
- * @param compName The component that is enabled.
- * @param userId The user id of the caller.
- * @param forUserId The user id they're making the request on behalf of.
- * @return True if the component is enabled, false otherwise
- */
- private boolean isEnabledNotificationListener(ComponentName compName, int userId,
- int forUserId) {
- if (userId != forUserId) {
- // You may not access another user's content as an enabled listener.
- return false;
- }
- if (DEBUG) {
- Log.d(TAG, "Checking if enabled notification listener " + compName);
- }
- if (compName != null) {
- try {
- return mNotificationManager.isNotificationListenerAccessGrantedForUser(
- compName, userId);
- } catch (RemoteException e) {
- Log.w(TAG, "Dead NotificationManager in isEnabledNotificationListener", e);
- }
- }
- return false;
- }
-
- private MediaSessionRecord createSessionInternal(int callerPid, int callerUid, int userId,
- String callerPackageName, ISessionCallback cb, String tag, Bundle sessionInfo)
- throws RemoteException {
- synchronized (mLock) {
- return createSessionLocked(callerPid, callerUid, userId, callerPackageName, cb,
- tag, sessionInfo);
- }
- }
-
- /*
- * When a session is created the following things need to happen.
- * 1. Its callback binder needs a link to death
- * 2. It needs to be added to all sessions.
- * 3. It needs to be added to the priority stack.
- * 4. It needs to be added to the relevant user record.
- */
- private MediaSessionRecord createSessionLocked(int callerPid, int callerUid, int userId,
- String callerPackageName, ISessionCallback cb, String tag, Bundle sessionInfo) {
- FullUserRecord user = getFullUserRecordLocked(userId);
- if (user == null) {
- Log.w(TAG, "Request from invalid user: " + userId + ", pkg=" + callerPackageName);
- throw new RuntimeException("Session request from invalid user.");
- }
-
- final MediaSessionRecord session = new MediaSessionRecord(callerPid, callerUid, userId,
- callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper());
- try {
- cb.asBinder().linkToDeath(session, 0);
- } catch (RemoteException e) {
- throw new RuntimeException("Media Session owner died prematurely.", e);
- }
-
- user.mPriorityStack.addSession(session);
- mHandler.postSessionsChanged(userId);
-
- if (DEBUG) {
- Log.d(TAG, "Created session for " + callerPackageName + " with tag " + tag);
- }
- return session;
- }
-
- private int findIndexOfSessionsListenerLocked(IActiveSessionsListener listener) {
- for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
- if (mSessionsListeners.get(i).listener.asBinder() == listener.asBinder()) {
- return i;
- }
- }
- return -1;
- }
-
- private int findIndexOfSession2TokensListenerLocked(ISession2TokensListener listener) {
- for (int i = mSession2TokensListenerRecords.size() - 1; i >= 0; i--) {
- if (mSession2TokensListenerRecords.get(i).listener.asBinder() == listener.asBinder()) {
- return i;
- }
- }
- return -1;
- }
-
-
- private void pushSessionsChanged(int userId) {
- synchronized (mLock) {
- FullUserRecord user = getFullUserRecordLocked(userId);
- if (user == null) {
- Log.w(TAG, "pushSessionsChanged failed. No user with id=" + userId);
- return;
- }
- List<MediaSessionRecord> records = getActiveSessionsLocked(userId);
- int size = records.size();
- ArrayList<MediaSession.Token> tokens = new ArrayList<MediaSession.Token>();
- for (int i = 0; i < size; i++) {
- tokens.add(records.get(i).getSessionToken());
- }
- pushRemoteVolumeUpdateLocked(userId);
- for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
- SessionsListenerRecord record = mSessionsListeners.get(i);
- if (record.userId == USER_ALL || record.userId == userId) {
- try {
- record.listener.onActiveSessionsChanged(tokens);
- } catch (RemoteException e) {
- Log.w(TAG, "Dead ActiveSessionsListener in pushSessionsChanged, removing",
- e);
- mSessionsListeners.remove(i);
- }
- }
- }
- }
- }
-
- private void pushRemoteVolumeUpdateLocked(int userId) {
- FullUserRecord user = getFullUserRecordLocked(userId);
- if (user == null) {
- Log.w(TAG, "pushRemoteVolumeUpdateLocked failed. No user with id=" + userId);
- return;
- }
-
- synchronized (mLock) {
- int size = mRemoteVolumeControllers.beginBroadcast();
- MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
- MediaSession.Token token = record == null ? null : record.getSessionToken();
-
- for (int i = size - 1; i >= 0; i--) {
- try {
- IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
- cb.updateRemoteController(token);
- } catch (Exception e) {
- Log.w(TAG, "Error sending default remote volume.", e);
- }
- }
- mRemoteVolumeControllers.finishBroadcast();
- }
- }
-
- void pushSession2TokensChangedLocked(int userId) {
- List<Session2Token> allSession2Tokens = getSession2TokensLocked(USER_ALL);
- List<Session2Token> session2Tokens = getSession2TokensLocked(userId);
-
- for (int i = mSession2TokensListenerRecords.size() - 1; i >= 0; i--) {
- Session2TokensListenerRecord listenerRecord = mSession2TokensListenerRecords.get(i);
- try {
- if (listenerRecord.userId == USER_ALL) {
- listenerRecord.listener.onSession2TokensChanged(allSession2Tokens);
- } else if (listenerRecord.userId == userId) {
- listenerRecord.listener.onSession2TokensChanged(session2Tokens);
- }
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to notify Session2Token change. Removing listener.", e);
- mSession2TokensListenerRecords.remove(i);
- }
- }
- }
-
- /**
- * Called when the media button receiver for the {@code record} is changed.
- *
- * @param record the media session whose media button receiver is updated.
- */
- public void onMediaButtonReceiverChanged(MediaSessionRecord record) {
- synchronized (mLock) {
- FullUserRecord user = getFullUserRecordLocked(record.getUserId());
- MediaSessionRecord mediaButtonSession =
- user.mPriorityStack.getMediaButtonSession();
- if (record == mediaButtonSession) {
- user.rememberMediaButtonReceiverLocked(mediaButtonSession);
- }
- }
- }
-
- private String getCallingPackageName(int uid) {
- String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
- if (packages != null && packages.length > 0) {
- return packages[0];
- }
- return "";
- }
-
- private void dispatchVolumeKeyLongPressLocked(KeyEvent keyEvent) {
- if (mCurrentFullUserRecord.mOnVolumeKeyLongPressListener == null) {
- return;
- }
- try {
- mCurrentFullUserRecord.mOnVolumeKeyLongPressListener.onVolumeKeyLongPress(keyEvent);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to send " + keyEvent + " to volume key long-press listener");
- }
- }
-
- private FullUserRecord getFullUserRecordLocked(int userId) {
- int fullUserId = mFullUserIds.get(userId, -1);
- if (fullUserId < 0) {
- return null;
- }
- return mUserRecords.get(fullUserId);
- }
-
- private MediaSessionRecord getMediaSessionRecordLocked(MediaSession.Token sessionToken) {
- FullUserRecord user = getFullUserRecordLocked(UserHandle.getUserId(sessionToken.getUid()));
- if (user != null) {
- return user.mPriorityStack.getMediaSessionRecord(sessionToken);
- }
- return null;
- }
-
- /**
- * Information about a full user and its corresponding managed profiles.
- *
- * <p>Since the full user runs together with its managed profiles, a user wouldn't differentiate
- * them when he/she presses a media/volume button. So keeping media sessions for them in one
- * place makes more sense and increases the readability.</p>
- * <p>The contents of this object is guarded by {@link #mLock}.
- */
- final class FullUserRecord implements MediaSessionStack.OnMediaButtonSessionChangedListener {
- public static final int COMPONENT_TYPE_INVALID = 0;
- public static final int COMPONENT_TYPE_BROADCAST = 1;
- public static final int COMPONENT_TYPE_ACTIVITY = 2;
- public static final int COMPONENT_TYPE_SERVICE = 3;
- private static final String COMPONENT_NAME_USER_ID_DELIM = ",";
-
- private final int mFullUserId;
- private final MediaSessionStack mPriorityStack;
- private PendingIntent mLastMediaButtonReceiver;
- private ComponentName mRestoredMediaButtonReceiver;
- private int mRestoredMediaButtonReceiverComponentType;
- private int mRestoredMediaButtonReceiverUserId;
-
- private IOnVolumeKeyLongPressListener mOnVolumeKeyLongPressListener;
- private int mOnVolumeKeyLongPressListenerUid;
- private KeyEvent mInitialDownVolumeKeyEvent;
- private int mInitialDownVolumeStream;
- private boolean mInitialDownMusicOnly;
-
- private IOnMediaKeyListener mOnMediaKeyListener;
- private int mOnMediaKeyListenerUid;
- private ICallback mCallback;
-
- FullUserRecord(int fullUserId) {
- mFullUserId = fullUserId;
- mPriorityStack = new MediaSessionStack(mAudioPlayerStateMonitor, this);
- // Restore the remembered media button receiver before the boot.
- String mediaButtonReceiverInfo = Settings.Secure.getStringForUser(mContentResolver,
- Settings.System.MEDIA_BUTTON_RECEIVER, mFullUserId);
- if (mediaButtonReceiverInfo == null) {
- return;
- }
- String[] tokens = mediaButtonReceiverInfo.split(COMPONENT_NAME_USER_ID_DELIM);
- if (tokens == null || (tokens.length != 2 && tokens.length != 3)) {
- return;
- }
- mRestoredMediaButtonReceiver = ComponentName.unflattenFromString(tokens[0]);
- mRestoredMediaButtonReceiverUserId = Integer.parseInt(tokens[1]);
- if (tokens.length == 3) {
- mRestoredMediaButtonReceiverComponentType = Integer.parseInt(tokens[2]);
- } else {
- mRestoredMediaButtonReceiverComponentType =
- getComponentType(mRestoredMediaButtonReceiver);
- }
- }
-
- public void destroySessionsForUserLocked(int userId) {
- List<MediaSessionRecord> sessions = mPriorityStack.getPriorityList(false, userId);
- for (MediaSessionRecord session : sessions) {
- MediaSessionServiceImpl.this.destroySessionLocked(session);
- }
- }
-
- public void dumpLocked(PrintWriter pw, String prefix) {
- pw.print(prefix + "Record for full_user=" + mFullUserId);
- // Dump managed profile user ids associated with this user.
- int size = mFullUserIds.size();
- for (int i = 0; i < size; i++) {
- if (mFullUserIds.keyAt(i) != mFullUserIds.valueAt(i)
- && mFullUserIds.valueAt(i) == mFullUserId) {
- pw.print(", profile_user=" + mFullUserIds.keyAt(i));
- }
- }
- pw.println();
- String indent = prefix + " ";
- pw.println(indent + "Volume key long-press listener: " + mOnVolumeKeyLongPressListener);
- pw.println(indent + "Volume key long-press listener package: "
- + getCallingPackageName(mOnVolumeKeyLongPressListenerUid));
- pw.println(indent + "Media key listener: " + mOnMediaKeyListener);
- pw.println(indent + "Media key listener package: "
- + getCallingPackageName(mOnMediaKeyListenerUid));
- pw.println(indent + "Callback: " + mCallback);
- pw.println(indent + "Last MediaButtonReceiver: " + mLastMediaButtonReceiver);
- pw.println(indent + "Restored MediaButtonReceiver: " + mRestoredMediaButtonReceiver);
- pw.println(indent + "Restored MediaButtonReceiverComponentType: "
- + mRestoredMediaButtonReceiverComponentType);
- mPriorityStack.dump(pw, indent);
- pw.println(indent + "Session2Tokens:");
- for (int i = 0; i < mSession2TokensPerUser.size(); i++) {
- List<Session2Token> list = mSession2TokensPerUser.valueAt(i);
- if (list == null || list.size() == 0) {
- continue;
- }
- for (Session2Token token : list) {
- pw.println(indent + " " + token);
- }
- }
- }
-
- @Override
- public void onMediaButtonSessionChanged(MediaSessionRecord oldMediaButtonSession,
- MediaSessionRecord newMediaButtonSession) {
- if (DEBUG_KEY_EVENT) {
- Log.d(TAG, "Media button session is changed to " + newMediaButtonSession);
- }
- synchronized (mLock) {
- if (oldMediaButtonSession != null) {
- mHandler.postSessionsChanged(oldMediaButtonSession.getUserId());
- }
- if (newMediaButtonSession != null) {
- rememberMediaButtonReceiverLocked(newMediaButtonSession);
- mHandler.postSessionsChanged(newMediaButtonSession.getUserId());
- }
- pushAddressedPlayerChangedLocked();
- }
- }
-
- // Remember media button receiver and keep it in the persistent storage.
- public void rememberMediaButtonReceiverLocked(MediaSessionRecord record) {
- PendingIntent receiver = record.getMediaButtonReceiver();
- mLastMediaButtonReceiver = receiver;
- mRestoredMediaButtonReceiver = null;
- mRestoredMediaButtonReceiverComponentType = COMPONENT_TYPE_INVALID;
-
- String mediaButtonReceiverInfo = "";
- if (receiver != null) {
- ComponentName component = receiver.getIntent().getComponent();
- if (component != null
- && record.getPackageName().equals(component.getPackageName())) {
- String componentName = component.flattenToString();
- int componentType = getComponentType(component);
- mediaButtonReceiverInfo = String.join(COMPONENT_NAME_USER_ID_DELIM,
- componentName, String.valueOf(record.getUserId()),
- String.valueOf(componentType));
- }
- }
- Settings.Secure.putStringForUser(mContentResolver,
- Settings.System.MEDIA_BUTTON_RECEIVER, mediaButtonReceiverInfo,
- mFullUserId);
- }
-
- private void pushAddressedPlayerChangedLocked() {
- if (mCallback == null) {
- return;
- }
- try {
- MediaSessionRecord mediaButtonSession = getMediaButtonSessionLocked();
- if (mediaButtonSession != null) {
- mCallback.onAddressedPlayerChangedToMediaSession(
- mediaButtonSession.getSessionToken());
- } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
- mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
- mCurrentFullUserRecord.mLastMediaButtonReceiver
- .getIntent().getComponent());
- } else if (mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
- mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
- mCurrentFullUserRecord.mRestoredMediaButtonReceiver);
- }
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to pushAddressedPlayerChangedLocked", e);
- }
- }
-
- private MediaSessionRecord getMediaButtonSessionLocked() {
- return isGlobalPriorityActiveLocked()
- ? mGlobalPrioritySession : mPriorityStack.getMediaButtonSession();
- }
-
- private int getComponentType(@Nullable ComponentName componentName) {
- if (componentName == null) {
- return COMPONENT_TYPE_INVALID;
- }
- PackageManager pm = mContext.getPackageManager();
- try {
- ActivityInfo activityInfo = pm.getActivityInfo(componentName,
- PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.GET_ACTIVITIES);
- if (activityInfo != null) {
- return COMPONENT_TYPE_ACTIVITY;
- }
- } catch (NameNotFoundException e) {
- }
- try {
- ServiceInfo serviceInfo = pm.getServiceInfo(componentName,
- PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.GET_SERVICES);
- if (serviceInfo != null) {
- return COMPONENT_TYPE_SERVICE;
- }
- } catch (NameNotFoundException e) {
- }
- // Pick legacy behavior for BroadcastReceiver or unknown.
- return COMPONENT_TYPE_BROADCAST;
- }
- }
-
- final class SessionsListenerRecord implements IBinder.DeathRecipient {
- public final IActiveSessionsListener listener;
- public final ComponentName componentName;
- public final int userId;
- public final int pid;
- public final int uid;
-
- SessionsListenerRecord(IActiveSessionsListener listener,
- ComponentName componentName,
- int userId, int pid, int uid) {
- this.listener = listener;
- this.componentName = componentName;
- this.userId = userId;
- this.pid = pid;
- this.uid = uid;
- }
-
- @Override
- public void binderDied() {
- synchronized (mLock) {
- mSessionsListeners.remove(this);
- }
- }
- }
-
- final class Session2TokensListenerRecord implements IBinder.DeathRecipient {
- public final ISession2TokensListener listener;
- public final int userId;
-
- Session2TokensListenerRecord(ISession2TokensListener listener,
- int userId) {
- this.listener = listener;
- this.userId = userId;
- }
-
- @Override
- public void binderDied() {
- synchronized (mLock) {
- mSession2TokensListenerRecords.remove(this);
- }
- }
- }
-
- final class SettingsObserver extends ContentObserver {
- private final Uri mSecureSettingsUri = Settings.Secure.getUriFor(
- Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
-
- private SettingsObserver() {
- super(null);
- }
-
- private void observe() {
- mContentResolver.registerContentObserver(mSecureSettingsUri,
- false, this, USER_ALL);
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- updateActiveSessionListeners();
- }
- }
-
- class SessionManagerImpl extends ISessionManager.Stub {
- private static final String EXTRA_WAKELOCK_ACQUIRED =
- "android.media.AudioService.WAKELOCK_ACQUIRED";
- private static final int WAKELOCK_RELEASE_ON_FINISHED = 1980; // magic number
-
- private boolean mVoiceButtonDown = false;
- private boolean mVoiceButtonHandled = false;
-
- @Override
- public ISession createSession(String packageName, ISessionCallback cb, String tag,
- Bundle sessionInfo, int userId) throws RemoteException {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- enforcePackageName(packageName, uid);
- int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
- false /* allowAll */, true /* requireFull */, "createSession", packageName);
- if (cb == null) {
- throw new IllegalArgumentException("Controller callback cannot be null");
- }
- return createSessionInternal(pid, uid, resolvedUserId, packageName, cb, tag,
- sessionInfo).getSessionBinder();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void notifySession2Created(Session2Token sessionToken) throws RemoteException {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- if (DEBUG) {
- Log.d(TAG, "Session2 is created " + sessionToken);
- }
- if (uid != sessionToken.getUid()) {
- throw new SecurityException("Unexpected Session2Token's UID, expected=" + uid
- + " but actually=" + sessionToken.getUid());
- }
- Controller2Callback callback = new Controller2Callback(sessionToken);
- // Note: It's safe not to keep controller here because it wouldn't be GC'ed until
- // it's closed.
- // TODO: Keep controller as well for better readability
- // because the GC behavior isn't straightforward.
- MediaController2 controller = new MediaController2.Builder(mContext, sessionToken)
- .setControllerCallback(new HandlerExecutor(mHandler), callback)
- .build();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public List<MediaSession.Token> getSessions(ComponentName componentName, int userId) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
-
- try {
- int resolvedUserId = verifySessionsRequest(componentName, userId, pid, uid);
- ArrayList<MediaSession.Token> tokens = new ArrayList<>();
- synchronized (mLock) {
- List<MediaSessionRecord> records = getActiveSessionsLocked(resolvedUserId);
- for (MediaSessionRecord record : records) {
- tokens.add(record.getSessionToken());
- }
- }
- return tokens;
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public ParceledListSlice getSession2Tokens(int userId) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
-
- try {
- // Check that they can make calls on behalf of the user and
- // get the final user id
- int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
- true /* allowAll */, true /* requireFull */, "getSession2Tokens",
- null /* optional packageName */);
- List<Session2Token> result;
- synchronized (mLock) {
- result = getSession2TokensLocked(resolvedUserId);
- }
- return new ParceledListSlice(result);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void addSessionsListener(IActiveSessionsListener listener,
- ComponentName componentName, int userId) throws RemoteException {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
-
- try {
- int resolvedUserId = verifySessionsRequest(componentName, userId, pid, uid);
- synchronized (mLock) {
- int index = findIndexOfSessionsListenerLocked(listener);
- if (index != -1) {
- Log.w(TAG, "ActiveSessionsListener is already added, ignoring");
- return;
- }
- SessionsListenerRecord record = new SessionsListenerRecord(listener,
- componentName, resolvedUserId, pid, uid);
- try {
- listener.asBinder().linkToDeath(record, 0);
- } catch (RemoteException e) {
- Log.e(TAG, "ActiveSessionsListener is dead, ignoring it", e);
- return;
- }
- mSessionsListeners.add(record);
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void removeSessionsListener(IActiveSessionsListener listener)
- throws RemoteException {
- synchronized (mLock) {
- int index = findIndexOfSessionsListenerLocked(listener);
- if (index != -1) {
- SessionsListenerRecord record = mSessionsListeners.remove(index);
- try {
- record.listener.asBinder().unlinkToDeath(record, 0);
- } catch (Exception e) {
- // ignore exceptions, the record is being removed
- }
- }
- }
- }
-
- @Override
- public void addSession2TokensListener(ISession2TokensListener listener,
- int userId) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
-
- try {
- // Check that they can make calls on behalf of the user and get the final user id.
- int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
- true /* allowAll */, true /* requireFull */, "addSession2TokensListener",
- null /* optional packageName */);
- synchronized (mLock) {
- int index = findIndexOfSession2TokensListenerLocked(listener);
- if (index >= 0) {
- Log.w(TAG, "addSession2TokensListener is already added, ignoring");
- return;
- }
- mSession2TokensListenerRecords.add(
- new Session2TokensListenerRecord(listener, resolvedUserId));
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void removeSession2TokensListener(ISession2TokensListener listener) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
-
- try {
- synchronized (mLock) {
- int index = findIndexOfSession2TokensListenerLocked(listener);
- if (index >= 0) {
- Session2TokensListenerRecord listenerRecord =
- mSession2TokensListenerRecords.remove(index);
- try {
- listenerRecord.listener.asBinder().unlinkToDeath(listenerRecord, 0);
- } catch (Exception e) {
- // Ignore exception.
- }
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- /**
- * Handles the dispatching of the media button events to one of the
- * registered listeners, or if there was none, broadcast an
- * ACTION_MEDIA_BUTTON intent to the rest of the system.
- *
- * @param packageName The caller package
- * @param asSystemService {@code true} if the event sent to the session as if it was come
- * from the system service instead of the app process. This helps sessions to
- * distinguish between the key injection by the app and key events from the
- * hardware devices. Should be used only when the volume key events aren't handled
- * by foreground activity. {@code false} otherwise to tell session about the real
- * caller.
- * @param keyEvent a non-null KeyEvent whose key code is one of the
- * supported media buttons
- * @param needWakeLock true if a PARTIAL_WAKE_LOCK needs to be held
- * while this key event is dispatched.
- */
- @Override
- public void dispatchMediaKeyEvent(String packageName, boolean asSystemService,
- KeyEvent keyEvent, boolean needWakeLock) {
- if (keyEvent == null || !KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())) {
- Log.w(TAG, "Attempted to dispatch null or non-media key event.");
- return;
- }
-
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- if (DEBUG) {
- Log.d(TAG, "dispatchMediaKeyEvent, pkg=" + packageName + " pid=" + pid
- + ", uid=" + uid + ", asSystem=" + asSystemService + ", event="
- + keyEvent);
- }
- if (!isUserSetupComplete()) {
- // Global media key handling can have the side-effect of starting new
- // activities which is undesirable while setup is in progress.
- Slog.i(TAG, "Not dispatching media key event because user "
- + "setup is in progress.");
- return;
- }
-
- synchronized (mLock) {
- boolean isGlobalPriorityActive = isGlobalPriorityActiveLocked();
- if (isGlobalPriorityActive && uid != Process.SYSTEM_UID) {
- // Prevent dispatching key event through reflection while the global
- // priority session is active.
- Slog.i(TAG, "Only the system can dispatch media key event "
- + "to the global priority session.");
- return;
- }
- if (!isGlobalPriorityActive) {
- if (mCurrentFullUserRecord.mOnMediaKeyListener != null) {
- if (DEBUG_KEY_EVENT) {
- Log.d(TAG, "Send " + keyEvent + " to the media key listener");
- }
- try {
- mCurrentFullUserRecord.mOnMediaKeyListener.onMediaKey(keyEvent,
- new MediaKeyListenerResultReceiver(packageName, pid, uid,
- asSystemService, keyEvent, needWakeLock));
- return;
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to send " + keyEvent
- + " to the media key listener");
- }
- }
- }
- if (!isGlobalPriorityActive && isVoiceKey(keyEvent.getKeyCode())) {
- handleVoiceKeyEventLocked(packageName, pid, uid, asSystemService, keyEvent,
- needWakeLock);
- } else {
- dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
- keyEvent, needWakeLock);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public boolean dispatchMediaKeyEventToSessionAsSystemService(String packageName,
- MediaSession.Token sessionToken, KeyEvent keyEvent) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
- if (record == null) {
- if (DEBUG) {
- Log.d(TAG, "Failed to find session to dispatch key event.");
- }
- return false;
- }
- if (DEBUG) {
- Log.d(TAG, "dispatchMediaKeyEventToSessionAsSystemService, pkg="
- + packageName + ", pid=" + pid + ", uid=" + uid + ", sessionToken="
- + sessionToken + ", event=" + keyEvent + ", session=" + record);
- }
- return record.sendMediaButton(packageName, pid, uid, true /* asSystemService */,
- keyEvent, 0, null);
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void setCallback(ICallback callback) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- if (!UserHandle.isSameApp(uid, Process.BLUETOOTH_UID)) {
- throw new SecurityException("Only Bluetooth service processes can set"
- + " Callback");
- }
- synchronized (mLock) {
- int userId = UserHandle.getUserId(uid);
- FullUserRecord user = getFullUserRecordLocked(userId);
- if (user == null || user.mFullUserId != userId) {
- Log.w(TAG, "Only the full user can set the callback"
- + ", userId=" + userId);
- return;
- }
- user.mCallback = callback;
- Log.d(TAG, "The callback " + user.mCallback
- + " is set by " + getCallingPackageName(uid));
- if (user.mCallback == null) {
- return;
- }
- try {
- user.mCallback.asBinder().linkToDeath(
- new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- synchronized (mLock) {
- user.mCallback = null;
- }
- }
- }, 0);
- user.pushAddressedPlayerChangedLocked();
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to set callback", e);
- user.mCallback = null;
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void setOnVolumeKeyLongPressListener(IOnVolumeKeyLongPressListener listener) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- // Enforce SET_VOLUME_KEY_LONG_PRESS_LISTENER permission.
- if (mContext.checkPermission(
- android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER, pid, uid)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold the SET_VOLUME_KEY_LONG_PRESS_LISTENER"
- + " permission.");
- }
-
- synchronized (mLock) {
- int userId = UserHandle.getUserId(uid);
- FullUserRecord user = getFullUserRecordLocked(userId);
- if (user == null || user.mFullUserId != userId) {
- Log.w(TAG, "Only the full user can set the volume key long-press listener"
- + ", userId=" + userId);
- return;
- }
- if (user.mOnVolumeKeyLongPressListener != null
- && user.mOnVolumeKeyLongPressListenerUid != uid) {
- Log.w(TAG, "The volume key long-press listener cannot be reset"
- + " by another app , mOnVolumeKeyLongPressListener="
- + user.mOnVolumeKeyLongPressListenerUid
- + ", uid=" + uid);
- return;
- }
-
- user.mOnVolumeKeyLongPressListener = listener;
- user.mOnVolumeKeyLongPressListenerUid = uid;
-
- Log.d(TAG, "The volume key long-press listener "
- + listener + " is set by " + getCallingPackageName(uid));
-
- if (user.mOnVolumeKeyLongPressListener != null) {
- try {
- user.mOnVolumeKeyLongPressListener.asBinder().linkToDeath(
- new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- synchronized (mLock) {
- user.mOnVolumeKeyLongPressListener = null;
- }
- }
- }, 0);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to set death recipient "
- + user.mOnVolumeKeyLongPressListener);
- user.mOnVolumeKeyLongPressListener = null;
- }
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void setOnMediaKeyListener(IOnMediaKeyListener listener) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- // Enforce SET_MEDIA_KEY_LISTENER permission.
- if (mContext.checkPermission(
- android.Manifest.permission.SET_MEDIA_KEY_LISTENER, pid, uid)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold the SET_MEDIA_KEY_LISTENER permission.");
- }
-
- synchronized (mLock) {
- int userId = UserHandle.getUserId(uid);
- FullUserRecord user = getFullUserRecordLocked(userId);
- if (user == null || user.mFullUserId != userId) {
- Log.w(TAG, "Only the full user can set the media key listener"
- + ", userId=" + userId);
- return;
- }
- if (user.mOnMediaKeyListener != null && user.mOnMediaKeyListenerUid != uid) {
- Log.w(TAG, "The media key listener cannot be reset by another app. "
- + ", mOnMediaKeyListenerUid=" + user.mOnMediaKeyListenerUid
- + ", uid=" + uid);
- return;
- }
-
- user.mOnMediaKeyListener = listener;
- user.mOnMediaKeyListenerUid = uid;
-
- Log.d(TAG, "The media key listener " + user.mOnMediaKeyListener
- + " is set by " + getCallingPackageName(uid));
-
- if (user.mOnMediaKeyListener != null) {
- try {
- user.mOnMediaKeyListener.asBinder().linkToDeath(
- new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- synchronized (mLock) {
- user.mOnMediaKeyListener = null;
- }
- }
- }, 0);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to set death recipient " + user.mOnMediaKeyListener);
- user.mOnMediaKeyListener = null;
- }
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- /**
- * Handles the dispatching of the volume button events to one of the
- * registered listeners. If there's a volume key long-press listener and
- * there's no active global priority session, long-pressess will be sent to the
- * long-press listener instead of adjusting volume.
- *
- * @param packageName The caller's package name, obtained by Context#getPackageName()
- * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName()
- * @param asSystemService {@code true} if the event sent to the session as if it was come
- * from the system service instead of the app process. This helps sessions to
- * distinguish between the key injection by the app and key events from the
- * hardware devices. Should be used only when the volume key events aren't handled
- * by foreground activity. {@code false} otherwise to tell session about the real
- * caller.
- * @param keyEvent a non-null KeyEvent whose key code is one of the
- * {@link KeyEvent#KEYCODE_VOLUME_UP},
- * {@link KeyEvent#KEYCODE_VOLUME_DOWN},
- * or {@link KeyEvent#KEYCODE_VOLUME_MUTE}.
- * @param stream stream type to adjust volume.
- * @param musicOnly true if both UI nor haptic feedback aren't needed when adjust volume.
- */
- @Override
- public void dispatchVolumeKeyEvent(String packageName, String opPackageName,
- boolean asSystemService, KeyEvent keyEvent, int stream, boolean musicOnly) {
- if (keyEvent == null
- || (keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_UP
- && keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_DOWN
- && keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_MUTE)) {
- Log.w(TAG, "Attempted to dispatch null or non-volume key event.");
- return;
- }
-
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
-
- if (DEBUG_KEY_EVENT) {
- Log.d(TAG, "dispatchVolumeKeyEvent, pkg=" + packageName
- + ", opPkg=" + opPackageName + ", pid=" + pid + ", uid=" + uid
- + ", asSystem=" + asSystemService + ", event=" + keyEvent
- + ", stream=" + stream + ", musicOnly=" + musicOnly);
- }
-
- try {
- synchronized (mLock) {
- if (isGlobalPriorityActiveLocked()
- || mCurrentFullUserRecord.mOnVolumeKeyLongPressListener == null) {
- dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
- asSystemService, keyEvent, stream, musicOnly);
- } else {
- // TODO: Consider the case when both volume up and down keys are pressed
- // at the same time.
- if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
- if (keyEvent.getRepeatCount() == 0) {
- // Keeps the copy of the KeyEvent because it can be reused.
- mCurrentFullUserRecord.mInitialDownVolumeKeyEvent =
- KeyEvent.obtain(keyEvent);
- mCurrentFullUserRecord.mInitialDownVolumeStream = stream;
- mCurrentFullUserRecord.mInitialDownMusicOnly = musicOnly;
- mHandler.sendMessageDelayed(
- mHandler.obtainMessage(
- MessageHandler.MSG_VOLUME_INITIAL_DOWN,
- mCurrentFullUserRecord.mFullUserId, 0),
- mLongPressTimeout);
- }
- if (keyEvent.getRepeatCount() > 0 || keyEvent.isLongPress()) {
- mHandler.removeMessages(MessageHandler.MSG_VOLUME_INITIAL_DOWN);
- if (mCurrentFullUserRecord.mInitialDownVolumeKeyEvent != null) {
- dispatchVolumeKeyLongPressLocked(
- mCurrentFullUserRecord.mInitialDownVolumeKeyEvent);
- // Mark that the key is already handled.
- mCurrentFullUserRecord.mInitialDownVolumeKeyEvent = null;
- }
- dispatchVolumeKeyLongPressLocked(keyEvent);
- }
- } else { // if up
- mHandler.removeMessages(MessageHandler.MSG_VOLUME_INITIAL_DOWN);
- if (mCurrentFullUserRecord.mInitialDownVolumeKeyEvent != null
- && mCurrentFullUserRecord.mInitialDownVolumeKeyEvent
- .getDownTime() == keyEvent.getDownTime()) {
- // Short-press. Should change volume.
- dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
- asSystemService,
- mCurrentFullUserRecord.mInitialDownVolumeKeyEvent,
- mCurrentFullUserRecord.mInitialDownVolumeStream,
- mCurrentFullUserRecord.mInitialDownMusicOnly);
- dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
- asSystemService, keyEvent, stream, musicOnly);
- } else {
- dispatchVolumeKeyLongPressLocked(keyEvent);
- }
- }
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- private void dispatchVolumeKeyEventLocked(String packageName, String opPackageName, int pid,
- int uid, boolean asSystemService, KeyEvent keyEvent, int stream,
- boolean musicOnly) {
- boolean down = keyEvent.getAction() == KeyEvent.ACTION_DOWN;
- boolean up = keyEvent.getAction() == KeyEvent.ACTION_UP;
- int direction = 0;
- boolean isMute = false;
- switch (keyEvent.getKeyCode()) {
- case KeyEvent.KEYCODE_VOLUME_UP:
- direction = AudioManager.ADJUST_RAISE;
- break;
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- direction = AudioManager.ADJUST_LOWER;
- break;
- case KeyEvent.KEYCODE_VOLUME_MUTE:
- isMute = true;
- break;
- }
- if (down || up) {
- int flags = AudioManager.FLAG_FROM_KEY;
- if (musicOnly) {
- // This flag is used when the screen is off to only affect active media.
- flags |= AudioManager.FLAG_ACTIVE_MEDIA_ONLY;
- } else {
- // These flags are consistent with the home screen
- if (up) {
- flags |= AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE;
- } else {
- flags |= AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE;
- }
- }
- if (direction != 0) {
- // If this is action up we want to send a beep for non-music events
- if (up) {
- direction = 0;
- }
- dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid,
- asSystemService, stream, direction, flags);
- } else if (isMute) {
- if (down && keyEvent.getRepeatCount() == 0) {
- dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid,
- asSystemService, stream, AudioManager.ADJUST_TOGGLE_MUTE, flags);
- }
- }
- }
- }
-
- @Override
- public void dispatchVolumeKeyEventToSessionAsSystemService(String packageName,
- String opPackageName, MediaSession.Token sessionToken, KeyEvent keyEvent) {
- int pid = Binder.getCallingPid();
- int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
- if (record == null) {
- if (DEBUG) {
- Log.d(TAG, "Failed to find session to dispatch key event.");
- }
- return;
- }
- if (DEBUG) {
- Log.d(TAG, "dispatchVolumeKeyEventToSessionAsSystemService, pkg="
- + packageName + ", opPkg=" + opPackageName + ", pid=" + pid
- + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event="
- + keyEvent + ", session=" + record);
- }
- switch (keyEvent.getAction()) {
- case KeyEvent.ACTION_DOWN: {
- int direction = 0;
- switch (keyEvent.getKeyCode()) {
- case KeyEvent.KEYCODE_VOLUME_UP:
- direction = AudioManager.ADJUST_RAISE;
- break;
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- direction = AudioManager.ADJUST_LOWER;
- break;
- case KeyEvent.KEYCODE_VOLUME_MUTE:
- direction = AudioManager.ADJUST_TOGGLE_MUTE;
- break;
- }
- record.adjustVolume(packageName, opPackageName, pid, uid,
- null /* caller */, true /* asSystemService */, direction,
- AudioManager.FLAG_SHOW_UI, false /* useSuggested */);
- break;
- }
-
- case KeyEvent.ACTION_UP: {
- final int flags =
- AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
- | AudioManager.FLAG_FROM_KEY;
- record.adjustVolume(packageName, opPackageName, pid, uid,
- null /* caller */, true /* asSystemService */, 0,
- flags, false /* useSuggested */);
- }
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void dispatchAdjustVolume(String packageName, String opPackageName,
- int suggestedStream, int delta, int flags) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid, false,
- suggestedStream, delta, flags);
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void registerRemoteVolumeController(IRemoteVolumeController rvc) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- synchronized (mLock) {
- try {
- enforceStatusBarServicePermission("listen for volume changes", pid, uid);
- mRemoteVolumeControllers.register(rvc);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- }
-
- @Override
- public void unregisterRemoteVolumeController(IRemoteVolumeController rvc) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- synchronized (mLock) {
- try {
- enforceStatusBarServicePermission("listen for volume changes", pid, uid);
- mRemoteVolumeControllers.unregister(rvc);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- }
-
- @Override
- public boolean isGlobalPriorityActive() {
- synchronized (mLock) {
- return isGlobalPriorityActiveLocked();
- }
- }
-
- @Override
- public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
- if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
-
- pw.println("MEDIA SESSION SERVICE (dumpsys media_session)");
- pw.println();
-
- synchronized (mLock) {
- pw.println(mSessionsListeners.size() + " sessions listeners.");
- pw.println("Global priority session is " + mGlobalPrioritySession);
- if (mGlobalPrioritySession != null) {
- mGlobalPrioritySession.dump(pw, " ");
- }
- pw.println("User Records:");
- int count = mUserRecords.size();
- for (int i = 0; i < count; i++) {
- mUserRecords.valueAt(i).dumpLocked(pw, "");
- }
- mAudioPlayerStateMonitor.dump(mContext, pw, "");
- }
- }
-
- /**
- * Returns if the controller's package is trusted (i.e. has either MEDIA_CONTENT_CONTROL
- * permission or an enabled notification listener)
- *
- * @param controllerPackageName package name of the controller app
- * @param controllerPid pid of the controller app
- * @param controllerUid uid of the controller app
- */
- @Override
- public boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid)
- throws RemoteException {
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- // Don't perform sanity check between controllerPackageName and controllerUid.
- // When an (activity|service) runs on the another apps process by specifying
- // android:process in the AndroidManifest.xml, then PID and UID would have the
- // running process' information instead of the (activity|service) that has created
- // MediaController.
- // Note that we can use Context#getOpPackageName() instead of
- // Context#getPackageName() for getting package name that matches with the PID/UID,
- // but it doesn't tell which package has created the MediaController, so useless.
- return hasMediaControlPermission(UserHandle.getUserId(uid), controllerPackageName,
- controllerPid, controllerUid);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- // For MediaSession
- private int verifySessionsRequest(ComponentName componentName, int userId, final int pid,
- final int uid) {
- String packageName = null;
- if (componentName != null) {
- // If they gave us a component name verify they own the
- // package
- packageName = componentName.getPackageName();
- enforcePackageName(packageName, uid);
- }
- // Check that they can make calls on behalf of the user and
- // get the final user id
- int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
- true /* allowAll */, true /* requireFull */, "getSessions", packageName);
- // Check if they have the permissions or their component is
- // enabled for the user they're calling from.
- enforceMediaPermissions(componentName, pid, uid, resolvedUserId);
- return resolvedUserId;
- }
-
- private boolean hasMediaControlPermission(int resolvedUserId, String packageName,
- int pid, int uid) throws RemoteException {
- // Allow API calls from the System UI and Settings
- if (hasStatusBarServicePermission(pid, uid)) {
- return true;
- }
-
- // Check if it's system server or has MEDIA_CONTENT_CONTROL.
- // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
- // check here.
- if (uid == Process.SYSTEM_UID || mContext.checkPermission(
- android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
- == PackageManager.PERMISSION_GRANTED) {
- return true;
- } else if (DEBUG) {
- Log.d(TAG, packageName + " (uid=" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
- }
-
- // You may not access another user's content as an enabled listener.
- final int userId = UserHandle.getUserId(uid);
- if (resolvedUserId != userId) {
- return false;
- }
-
- // TODO(jaewan): (Post-P) Propose NotificationManager#hasEnabledNotificationListener(
- // String pkgName) to notification team for optimization
- final List<ComponentName> enabledNotificationListeners =
- mNotificationManager.getEnabledNotificationListeners(userId);
- if (enabledNotificationListeners != null) {
- for (int i = 0; i < enabledNotificationListeners.size(); i++) {
- if (TextUtils.equals(packageName,
- enabledNotificationListeners.get(i).getPackageName())) {
- return true;
- }
- }
- }
- if (DEBUG) {
- Log.d(TAG, packageName + " (uid=" + uid + ") doesn't have an enabled "
- + "notification listener");
- }
- return false;
- }
-
- private void dispatchAdjustVolumeLocked(String packageName, String opPackageName, int pid,
- int uid, boolean asSystemService, int suggestedStream, int direction, int flags) {
- MediaSessionRecord session = isGlobalPriorityActiveLocked() ? mGlobalPrioritySession
- : mCurrentFullUserRecord.mPriorityStack.getDefaultVolumeSession();
-
- boolean preferSuggestedStream = false;
- if (isValidLocalStreamType(suggestedStream)
- && AudioSystem.isStreamActive(suggestedStream, 0)) {
- preferSuggestedStream = true;
- }
- if (DEBUG_KEY_EVENT) {
- Log.d(TAG, "Adjusting " + session + " by " + direction + ". flags="
- + flags + ", suggestedStream=" + suggestedStream
- + ", preferSuggestedStream=" + preferSuggestedStream);
- }
- if (session == null || preferSuggestedStream) {
- if ((flags & AudioManager.FLAG_ACTIVE_MEDIA_ONLY) != 0
- && !AudioSystem.isStreamActive(AudioManager.STREAM_MUSIC, 0)) {
- if (DEBUG) {
- Log.d(TAG, "No active session to adjust, skipping media only volume event");
- }
- return;
- }
-
- // Execute mAudioService.adjustSuggestedStreamVolume() on
- // handler thread of MediaSessionService.
- // This will release the MediaSessionService.mLock sooner and avoid
- // a potential deadlock between MediaSessionService.mLock and
- // ActivityManagerService lock.
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- final String callingOpPackageName;
- final int callingUid;
- if (asSystemService) {
- callingOpPackageName = mContext.getOpPackageName();
- callingUid = Process.myUid();
- } else {
- callingOpPackageName = opPackageName;
- callingUid = uid;
- }
- try {
- mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(suggestedStream,
- direction, flags, callingOpPackageName, callingUid);
- } catch (SecurityException | IllegalArgumentException e) {
- Log.e(TAG, "Cannot adjust volume: direction=" + direction
- + ", suggestedStream=" + suggestedStream + ", flags=" + flags
- + ", packageName=" + packageName + ", uid=" + uid
- + ", asSystemService=" + asSystemService, e);
- }
- }
- });
- } else {
- session.adjustVolume(packageName, opPackageName, pid, uid, null, asSystemService,
- direction, flags, true);
- }
- }
-
- private void handleVoiceKeyEventLocked(String packageName, int pid, int uid,
- boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
- int action = keyEvent.getAction();
- boolean isLongPress = (keyEvent.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0;
- if (action == KeyEvent.ACTION_DOWN) {
- if (keyEvent.getRepeatCount() == 0) {
- mVoiceButtonDown = true;
- mVoiceButtonHandled = false;
- } else if (mVoiceButtonDown && !mVoiceButtonHandled && isLongPress) {
- mVoiceButtonHandled = true;
- startVoiceInput(needWakeLock);
- }
- } else if (action == KeyEvent.ACTION_UP) {
- if (mVoiceButtonDown) {
- mVoiceButtonDown = false;
- if (!mVoiceButtonHandled && !keyEvent.isCanceled()) {
- // Resend the down then send this event through
- KeyEvent downEvent = KeyEvent.changeAction(keyEvent, KeyEvent.ACTION_DOWN);
- dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
- downEvent, needWakeLock);
- dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
- keyEvent, needWakeLock);
- }
- }
- }
- }
-
- private void dispatchMediaKeyEventLocked(String packageName, int pid, int uid,
- boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
- MediaSessionRecord session = mCurrentFullUserRecord.getMediaButtonSessionLocked();
- if (session != null) {
- if (DEBUG_KEY_EVENT) {
- Log.d(TAG, "Sending " + keyEvent + " to " + session);
- }
- if (needWakeLock) {
- mKeyEventReceiver.aquireWakeLockLocked();
- }
- // If we don't need a wakelock use -1 as the id so we won't release it later.
- session.sendMediaButton(packageName, pid, uid, asSystemService, keyEvent,
- needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
- mKeyEventReceiver);
- if (mCurrentFullUserRecord.mCallback != null) {
- try {
- mCurrentFullUserRecord.mCallback.onMediaKeyEventDispatchedToMediaSession(
- keyEvent, session.getSessionToken());
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to send callback", e);
- }
- }
- } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null
- || mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
- if (needWakeLock) {
- mKeyEventReceiver.aquireWakeLockLocked();
- }
- Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
- mediaButtonIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
- // TODO: Find a way to also send PID/UID in secure way.
- String callerPackageName =
- (asSystemService) ? mContext.getPackageName() : packageName;
- mediaButtonIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, callerPackageName);
- try {
- if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
- PendingIntent receiver = mCurrentFullUserRecord.mLastMediaButtonReceiver;
- if (DEBUG_KEY_EVENT) {
- Log.d(TAG, "Sending " + keyEvent
- + " to the last known PendingIntent " + receiver);
- }
- receiver.send(mContext,
- needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
- mediaButtonIntent, mKeyEventReceiver, mHandler);
- if (mCurrentFullUserRecord.mCallback != null) {
- ComponentName componentName = mCurrentFullUserRecord
- .mLastMediaButtonReceiver.getIntent().getComponent();
- if (componentName != null) {
- mCurrentFullUserRecord.mCallback
- .onMediaKeyEventDispatchedToMediaButtonReceiver(
- keyEvent, componentName);
- }
- }
- } else {
- ComponentName receiver =
- mCurrentFullUserRecord.mRestoredMediaButtonReceiver;
- int componentType = mCurrentFullUserRecord
- .mRestoredMediaButtonReceiverComponentType;
- UserHandle userHandle = UserHandle.of(mCurrentFullUserRecord
- .mRestoredMediaButtonReceiverUserId);
- if (DEBUG_KEY_EVENT) {
- Log.d(TAG, "Sending " + keyEvent + " to the restored intent "
- + receiver + ", type=" + componentType);
- }
- mediaButtonIntent.setComponent(receiver);
- try {
- switch (componentType) {
- case FullUserRecord.COMPONENT_TYPE_ACTIVITY:
- mContext.startActivityAsUser(mediaButtonIntent, userHandle);
- break;
- case FullUserRecord.COMPONENT_TYPE_SERVICE:
- mContext.startForegroundServiceAsUser(mediaButtonIntent,
- userHandle);
- break;
- default:
- // Legacy behavior for other cases.
- mContext.sendBroadcastAsUser(mediaButtonIntent, userHandle);
- }
- } catch (Exception e) {
- Log.w(TAG, "Error sending media button to the restored intent "
- + receiver + ", type=" + componentType, e);
- }
- if (mCurrentFullUserRecord.mCallback != null) {
- mCurrentFullUserRecord.mCallback
- .onMediaKeyEventDispatchedToMediaButtonReceiver(
- keyEvent, receiver);
- }
- }
- } catch (CanceledException e) {
- Log.i(TAG, "Error sending key event to media button receiver "
- + mCurrentFullUserRecord.mLastMediaButtonReceiver, e);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to send callback", e);
- }
- }
- }
-
- private void startVoiceInput(boolean needWakeLock) {
- Intent voiceIntent = null;
- // select which type of search to launch:
- // - screen on and device unlocked: action is ACTION_WEB_SEARCH
- // - device locked or screen off: action is
- // ACTION_VOICE_SEARCH_HANDS_FREE
- // with EXTRA_SECURE set to true if the device is securely locked
- PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- boolean isLocked = mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
- if (!isLocked && pm.isScreenOn()) {
- voiceIntent = new Intent(android.speech.RecognizerIntent.ACTION_WEB_SEARCH);
- Log.i(TAG, "voice-based interactions: about to use ACTION_WEB_SEARCH");
- } else {
- voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
- voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE,
- isLocked && mKeyguardManager.isKeyguardSecure());
- Log.i(TAG, "voice-based interactions: about to use ACTION_VOICE_SEARCH_HANDS_FREE");
- }
- // start the search activity
- if (needWakeLock) {
- mMediaEventWakeLock.acquire();
- }
- try {
- if (voiceIntent != null) {
- voiceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- if (DEBUG) Log.d(TAG, "voiceIntent: " + voiceIntent);
- mContext.startActivityAsUser(voiceIntent, UserHandle.CURRENT);
- }
- } catch (ActivityNotFoundException e) {
- Log.w(TAG, "No activity for search: " + e);
- } finally {
- if (needWakeLock) {
- mMediaEventWakeLock.release();
- }
- }
- }
-
- private boolean isVoiceKey(int keyCode) {
- return keyCode == KeyEvent.KEYCODE_HEADSETHOOK
- || (!mHasFeatureLeanback && keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
- }
-
- private boolean isUserSetupComplete() {
- return Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
- }
-
- // we only handle public stream types, which are 0-5
- private boolean isValidLocalStreamType(int streamType) {
- return streamType >= AudioManager.STREAM_VOICE_CALL
- && streamType <= AudioManager.STREAM_NOTIFICATION;
- }
-
- private class MediaKeyListenerResultReceiver extends ResultReceiver implements Runnable {
- private final String mPackageName;
- private final int mPid;
- private final int mUid;
- private final boolean mAsSystemService;
- private final KeyEvent mKeyEvent;
- private final boolean mNeedWakeLock;
- private boolean mHandled;
-
- private MediaKeyListenerResultReceiver(String packageName, int pid, int uid,
- boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
- super(mHandler);
- mHandler.postDelayed(this, MEDIA_KEY_LISTENER_TIMEOUT);
- mPackageName = packageName;
- mPid = pid;
- mUid = uid;
- mAsSystemService = asSystemService;
- mKeyEvent = keyEvent;
- mNeedWakeLock = needWakeLock;
- }
-
- @Override
- public void run() {
- Log.d(TAG, "The media key listener is timed-out for " + mKeyEvent);
- dispatchMediaKeyEvent();
- }
-
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode == MediaSessionManager.RESULT_MEDIA_KEY_HANDLED) {
- mHandled = true;
- mHandler.removeCallbacks(this);
- return;
- }
- dispatchMediaKeyEvent();
- }
-
- private void dispatchMediaKeyEvent() {
- if (mHandled) {
- return;
- }
- mHandled = true;
- mHandler.removeCallbacks(this);
- synchronized (mLock) {
- if (!isGlobalPriorityActiveLocked()
- && isVoiceKey(mKeyEvent.getKeyCode())) {
- handleVoiceKeyEventLocked(mPackageName, mPid, mUid, mAsSystemService,
- mKeyEvent, mNeedWakeLock);
- } else {
- dispatchMediaKeyEventLocked(mPackageName, mPid, mUid, mAsSystemService,
- mKeyEvent, mNeedWakeLock);
- }
- }
- }
- }
-
- private KeyEventWakeLockReceiver mKeyEventReceiver = new KeyEventWakeLockReceiver(mHandler);
-
- class KeyEventWakeLockReceiver extends ResultReceiver implements Runnable,
- PendingIntent.OnFinished {
- private final Handler mHandler;
- private int mRefCount = 0;
- private int mLastTimeoutId = 0;
-
- KeyEventWakeLockReceiver(Handler handler) {
- super(handler);
- mHandler = handler;
- }
-
- public void onTimeout() {
- synchronized (mLock) {
- if (mRefCount == 0) {
- // We've already released it, so just return
- return;
- }
- mLastTimeoutId++;
- mRefCount = 0;
- releaseWakeLockLocked();
- }
- }
-
- public void aquireWakeLockLocked() {
- if (mRefCount == 0) {
- mMediaEventWakeLock.acquire();
- }
- mRefCount++;
- mHandler.removeCallbacks(this);
- mHandler.postDelayed(this, WAKELOCK_TIMEOUT);
-
- }
-
- @Override
- public void run() {
- onTimeout();
- }
-
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode < mLastTimeoutId) {
- // Ignore results from calls that were before the last
- // timeout, just in case.
- return;
- } else {
- synchronized (mLock) {
- if (mRefCount > 0) {
- mRefCount--;
- if (mRefCount == 0) {
- releaseWakeLockLocked();
- }
- }
- }
- }
- }
-
- private void releaseWakeLockLocked() {
- mMediaEventWakeLock.release();
- mHandler.removeCallbacks(this);
- }
-
- @Override
- public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
- String resultData, Bundle resultExtras) {
- onReceiveResult(resultCode, null);
- }
- };
-
- BroadcastReceiver mKeyEventDone = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent == null) {
- return;
- }
- Bundle extras = intent.getExtras();
- if (extras == null) {
- return;
- }
- synchronized (mLock) {
- if (extras.containsKey(EXTRA_WAKELOCK_ACQUIRED)
- && mMediaEventWakeLock.isHeld()) {
- mMediaEventWakeLock.release();
- }
- }
- }
- };
- }
-
- final class MessageHandler extends Handler {
- private static final int MSG_SESSIONS_CHANGED = 1;
- private static final int MSG_VOLUME_INITIAL_DOWN = 2;
- private final SparseArray<Integer> mIntegerCache = new SparseArray<>();
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_SESSIONS_CHANGED:
- pushSessionsChanged((int) msg.obj);
- break;
- case MSG_VOLUME_INITIAL_DOWN:
- synchronized (mLock) {
- FullUserRecord user = mUserRecords.get((int) msg.arg1);
- if (user != null && user.mInitialDownVolumeKeyEvent != null) {
- dispatchVolumeKeyLongPressLocked(user.mInitialDownVolumeKeyEvent);
- // Mark that the key is already handled.
- user.mInitialDownVolumeKeyEvent = null;
- }
- }
- break;
- }
- }
-
- public void postSessionsChanged(int userId) {
- // Use object instead of the arguments when posting message to remove pending requests.
- Integer userIdInteger = mIntegerCache.get(userId);
- if (userIdInteger == null) {
- userIdInteger = Integer.valueOf(userId);
- mIntegerCache.put(userId, userIdInteger);
- }
- removeMessages(MSG_SESSIONS_CHANGED, userIdInteger);
- obtainMessage(MSG_SESSIONS_CHANGED, userIdInteger).sendToTarget();
- }
- }
-
- private class Controller2Callback extends MediaController2.ControllerCallback {
- private final Session2Token mToken;
-
- Controller2Callback(Session2Token token) {
- mToken = token;
- }
-
- @Override
- public void onConnected(MediaController2 controller, Session2CommandGroup allowedCommands) {
- synchronized (mLock) {
- int userId = UserHandle.getUserId(mToken.getUid());
- mSession2TokensPerUser.get(userId).add(mToken);
- pushSession2TokensChangedLocked(userId);
- }
- }
-
- @Override
- public void onDisconnected(MediaController2 controller) {
- synchronized (mLock) {
- int userId = UserHandle.getUserId(mToken.getUid());
- mSession2TokensPerUser.get(userId).remove(mToken);
- pushSession2TokensChangedLocked(userId);
- }
- }
- }
-}
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 5d667b6..9e509f4 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -282,13 +282,14 @@
throw new IllegalArgumentException("package name must not be empty");
}
+ final UserHandle callingUser = Binder.getCallingUserHandle();
long callingToken = Binder.clearCallingIdentity();
MediaProjection projection;
try {
ApplicationInfo ai;
try {
- ai = mPackageManager.getApplicationInfo(packageName, 0);
+ ai = mPackageManager.getApplicationInfoAsUser(packageName, 0, callingUser);
} catch (NameNotFoundException e) {
throw new IllegalArgumentException("No package matching :" + packageName);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index cdcb641..4f85941 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -181,7 +181,6 @@
import android.service.notification.NotificationRecordProto;
import android.service.notification.NotificationServiceDumpProto;
import android.service.notification.NotificationStats;
-import android.service.notification.NotifyingApp;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
@@ -413,7 +412,6 @@
final ArrayMap<Integer, ArrayMap<String, String>> mAutobundledSummaries = new ArrayMap<>();
final ArrayList<ToastRecord> mToastQueue = new ArrayList<>();
final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>();
- final ArrayMap<Integer, ArrayList<NotifyingApp>> mRecentApps = new ArrayMap<>();
// The last key in this list owns the hardware.
ArrayList<String> mLights = new ArrayList<>();
@@ -2209,7 +2207,6 @@
mAppUsageStats.reportInterruptiveNotification(r.sbn.getPackageName(),
r.getChannel().getId(),
getRealUserId(r.sbn.getUserId()));
- logRecentLocked(r);
r.setRecordedInterruption(true);
}
}
@@ -2465,7 +2462,8 @@
*/
@Override
public boolean areNotificationsEnabledForPackage(String pkg, int uid) {
- checkCallerIsSystemOrSameApp(pkg);
+ enforceSystemOrSystemUIOrSamePackage(pkg,
+ "Caller not system or systemui or same package");
if (UserHandle.getCallingUserId() != UserHandle.getUserId(uid)) {
getContext().enforceCallingPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS,
@@ -2791,7 +2789,7 @@
@Override
public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage(
String pkg, int uid, boolean includeDeleted) {
- checkCallerIsSystem();
+ enforceSystemOrSystemUI("getNotificationChannelGroupsForPackage");
return mPreferencesHelper.getNotificationChannelGroups(
pkg, uid, includeDeleted, true, false);
}
@@ -2830,16 +2828,6 @@
}
@Override
- public ParceledListSlice<NotifyingApp> getRecentNotifyingAppsForUser(int userId) {
- checkCallerIsSystem();
- synchronized (mNotificationLock) {
- List<NotifyingApp> apps = new ArrayList<>(
- mRecentApps.getOrDefault(userId, new ArrayList<>()));
- return new ParceledListSlice<>(apps);
- }
- }
-
- @Override
public int getBlockedAppCount(int userId) {
checkCallerIsSystem();
return mPreferencesHelper.getBlockedAppCount(userId);
@@ -5527,38 +5515,6 @@
}
/**
- * Keeps the last 5 packages that have notified, by user.
- */
- @GuardedBy("mNotificationLock")
- @VisibleForTesting
- protected void logRecentLocked(NotificationRecord r) {
- if (r.isUpdate) {
- return;
- }
- ArrayList<NotifyingApp> recentAppsForUser =
- mRecentApps.getOrDefault(r.getUser().getIdentifier(), new ArrayList<>(6));
- NotifyingApp na = new NotifyingApp()
- .setPackage(r.sbn.getPackageName())
- .setUid(r.sbn.getUid())
- .setLastNotified(r.sbn.getPostTime());
- // A new notification gets an app moved to the front of the list
- for (int i = recentAppsForUser.size() - 1; i >= 0; i--) {
- NotifyingApp naExisting = recentAppsForUser.get(i);
- if (na.getPackage().equals(naExisting.getPackage())
- && na.getUid() == naExisting.getUid()) {
- recentAppsForUser.remove(i);
- break;
- }
- }
- // time is always increasing, so always add to the front of the list
- recentAppsForUser.add(0, na);
- if (recentAppsForUser.size() > 5) {
- recentAppsForUser.remove(recentAppsForUser.size() -1);
- }
- mRecentApps.put(r.getUser().getIdentifier(), recentAppsForUser);
- }
-
- /**
* Ensures that grouped notification receive their special treatment.
*
* <p>Cancels group children if the new notification causes a group to lose
@@ -7380,8 +7336,7 @@
static final String TAG_ENABLED_NOTIFICATION_ASSISTANTS = "enabled_assistants";
private static final String ATT_USER_SET = "user_set";
- // TODO: STOPSHIP (b/127994217) switch to final value when onboarding flow is implemented
- private static final String TAG_ALLOWED_ADJUSTMENT_TYPES = "allowed_adjustments_tmp2";
+ private static final String TAG_ALLOWED_ADJUSTMENT_TYPES = "allowed_adjustments";
private static final String ATT_TYPES = "types";
private final Object mLock = new Object();
@@ -7394,7 +7349,6 @@
IPackageManager pm) {
super(context, lock, up, pm);
- // TODO: STOPSHIP (b/127994217) remove when the onboarding flow is implemented
// Add all default allowed adjustment types. Will be overwritten by values in xml,
// if they exist
for (int i = 0; i < DEFAULT_ALLOWED_ADJUSTMENTS.length; i++) {
@@ -7463,9 +7417,9 @@
protected void readExtraTag(String tag, XmlPullParser parser) throws IOException {
if (TAG_ALLOWED_ADJUSTMENT_TYPES.equals(tag)) {
final String types = XmlUtils.readStringAttribute(parser, ATT_TYPES);
- if (!TextUtils.isEmpty(types)) {
- synchronized (mLock) {
- mAllowedAdjustments.clear();
+ synchronized (mLock) {
+ mAllowedAdjustments.clear();
+ if (!TextUtils.isEmpty(types)) {
mAllowedAdjustments.addAll(Arrays.asList(types.split(",")));
}
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 627b65c..3f1a248 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -92,13 +92,13 @@
private static final String ATT_APP_USER_LOCKED_FIELDS = "app_user_locked_fields";
private static final String ATT_ENABLED = "enabled";
private static final String ATT_USER_ALLOWED = "allowed";
- private static final String ATT_HIDE_SILENT = "hide_silent";
+ private static final String ATT_HIDE_SILENT = "hide_gentle";
private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT;
private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED;
@VisibleForTesting
- static final boolean DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS = true;
+ static final boolean DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS = false;
private static final boolean DEFAULT_SHOW_BADGE = true;
private static final boolean DEFAULT_ALLOW_BUBBLE = true;
private static final boolean DEFAULT_OEM_LOCKED_IMPORTANCE = false;
diff --git a/services/core/java/com/android/server/om/DumpState.java b/services/core/java/com/android/server/om/DumpState.java
new file mode 100644
index 0000000..1e2e054
--- /dev/null
+++ b/services/core/java/com/android/server/om/DumpState.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.om;
+
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.os.UserHandle;
+
+/**
+ * State for dumps performed by the OverlayManagerService.
+ */
+public final class DumpState {
+ @UserIdInt private int mUserId = UserHandle.USER_ALL;
+ @Nullable private String mPackageName;
+ @Nullable private String mField;
+ private boolean mVerbose;
+
+ /** Sets the user to dump the state for */
+ public void setUserId(@UserIdInt int userId) {
+ mUserId = userId;
+ }
+ @UserIdInt public int getUserId() {
+ return mUserId;
+ }
+
+ /** Sets the name of the package to dump the state for */
+ public void setPackageName(String packageName) {
+ mPackageName = packageName;
+ }
+ @Nullable public String getPackageName() {
+ return mPackageName;
+ }
+
+ /** Sets the name of the field to dump the state of */
+ public void setField(String field) {
+ mField = field;
+ }
+ @Nullable public String getField() {
+ return mField;
+ }
+
+ /** Enables verbose dump state */
+ public void setVerbose(boolean verbose) {
+ mVerbose = verbose;
+ }
+ public boolean isVerbose() {
+ return mVerbose;
+ }
+}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 209ccda..da69986 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -749,15 +749,77 @@
}
@Override
- protected void dump(@NonNull final FileDescriptor fd, @NonNull final PrintWriter pw,
- @NonNull final String[] argv) {
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ final DumpState dumpState = new DumpState();
+ dumpState.setUserId(UserHandle.getUserId(Binder.getCallingUid()));
+
+ int opti = 0;
+ while (opti < args.length) {
+ final String opt = args[opti];
+ if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
+ break;
+ }
+ opti++;
+
+ if ("-h".equals(opt)) {
+ pw.println("dump [-h] [--verbose] [--user USER_ID] [[FIELD] PACKAGE]");
+ pw.println(" Print debugging information about the overlay manager.");
+ pw.println(" With optional parameter PACKAGE, limit output to the specified");
+ pw.println(" package. With optional parameter FIELD, limit output to");
+ pw.println(" the value of that SettingsItem field. Field names are");
+ pw.println(" case insensitive and out.println the m prefix can be omitted,");
+ pw.println(" so the following are equivalent: mState, mstate, State, state.");
+ return;
+ } else if ("--user".equals(opt)) {
+ opti++;
+ if (opti >= args.length) {
+ pw.println("Error: user missing argument");
+ return;
+ }
+ try {
+ dumpState.setUserId(Integer.parseInt(args[opti]));
+ } catch (NumberFormatException e) {
+ pw.println("Error: user argument is not a number: " + args[opti]);
+ return;
+ }
+ } else if ("--verbose".equals(opt)) {
+ dumpState.setVerbose(true);
+ } else {
+ pw.println("Unknown argument: " + opt + "; use -h for help");
+ }
+ }
+ if (opti < args.length) {
+ final String arg = args[opti];
+ opti++;
+ switch (arg) {
+ case "packagename":
+ case "userid":
+ case "targetpackagename":
+ case "targetoverlayablename":
+ case "basecodepath":
+ case "state":
+ case "isenabled":
+ case "isstatic":
+ case "priority":
+ case "category":
+ dumpState.setField(arg);
+ break;
+ default:
+ dumpState.setPackageName(arg);
+ break;
+ }
+ }
+ if (dumpState.getPackageName() == null && opti < args.length) {
+ dumpState.setPackageName(args[opti]);
+ opti++;
+ }
+
enforceDumpPermission("dump");
-
- final boolean verbose = argv.length > 0 && "--verbose".equals(argv[0]);
-
synchronized (mLock) {
- mImpl.onDump(pw);
- mPackageManager.dump(pw, verbose);
+ mImpl.dump(pw, dumpState);
+ if (dumpState.getPackageName() == null) {
+ mPackageManager.dump(pw, dumpState);
+ }
}
}
@@ -1046,10 +1108,10 @@
private static final String TAB1 = " ";
private static final String TAB2 = TAB1 + TAB1;
- public void dump(@NonNull final PrintWriter pw, final boolean verbose) {
+ public void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) {
pw.println("PackageInfo cache");
- if (!verbose) {
+ if (!dumpState.isVerbose()) {
int count = 0;
final int n = mCache.size();
for (int i = 0; i < n; i++) {
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 092dbc8..6f28675 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -636,9 +636,11 @@
return true;
}
- void onDump(@NonNull final PrintWriter pw) {
- mSettings.dump(pw);
- pw.println("Default overlays: " + TextUtils.join(";", mDefaultOverlays));
+ void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) {
+ mSettings.dump(pw, dumpState);
+ if (dumpState.getPackageName() == null) {
+ pw.println("Default overlays: " + TextUtils.join(";", mDefaultOverlays));
+ }
}
@NonNull String[] getDefaultOverlayPackages() {
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index f35c707..b7346d4 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.om.OverlayInfo;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Slog;
import android.util.Xml;
@@ -288,35 +289,78 @@
return true;
}
- void dump(@NonNull final PrintWriter p) {
- final IndentingPrintWriter pw = new IndentingPrintWriter(p, " ");
- pw.println("Settings");
- pw.increaseIndent();
-
- if (mItems.isEmpty()) {
- pw.println("<none>");
- return;
+ void dump(@NonNull final PrintWriter p, @NonNull DumpState dumpState) {
+ // select items to display
+ Stream<SettingsItem> items = mItems.stream();
+ if (dumpState.getUserId() != UserHandle.USER_ALL) {
+ items = items.filter(item -> item.mUserId == dumpState.getUserId());
+ }
+ if (dumpState.getPackageName() != null) {
+ items = items.filter(item -> item.mPackageName.equals(dumpState.getPackageName()));
}
- final int n = mItems.size();
- for (int i = 0; i < n; i++) {
- final SettingsItem item = mItems.get(i);
- pw.println(item.mPackageName + ":" + item.getUserId() + " {");
- pw.increaseIndent();
+ // display items
+ final IndentingPrintWriter pw = new IndentingPrintWriter(p, " ");
+ if (dumpState.getField() != null) {
+ items.forEach(item -> dumpSettingsItemField(pw, item, dumpState.getField()));
+ } else {
+ items.forEach(item -> dumpSettingsItem(pw, item));
+ }
+ }
- pw.println("mPackageName...........: " + item.mPackageName);
- pw.println("mUserId................: " + item.getUserId());
- pw.println("mTargetPackageName.....: " + item.getTargetPackageName());
- pw.println("mTargetOverlayableName.: " + item.getTargetOverlayableName());
- pw.println("mBaseCodePath..........: " + item.getBaseCodePath());
- pw.println("mState.................: " + OverlayInfo.stateToString(item.getState()));
- pw.println("mIsEnabled.............: " + item.isEnabled());
- pw.println("mIsStatic..............: " + item.isStatic());
- pw.println("mPriority..............: " + item.mPriority);
- pw.println("mCategory..............: " + item.mCategory);
+ private void dumpSettingsItem(@NonNull final IndentingPrintWriter pw,
+ @NonNull final SettingsItem item) {
+ pw.println(item.mPackageName + ":" + item.getUserId() + " {");
+ pw.increaseIndent();
- pw.decreaseIndent();
- pw.println("}");
+ pw.println("mPackageName...........: " + item.mPackageName);
+ pw.println("mUserId................: " + item.getUserId());
+ pw.println("mTargetPackageName.....: " + item.getTargetPackageName());
+ pw.println("mTargetOverlayableName.: " + item.getTargetOverlayableName());
+ pw.println("mBaseCodePath..........: " + item.getBaseCodePath());
+ pw.println("mState.................: " + OverlayInfo.stateToString(item.getState()));
+ pw.println("mIsEnabled.............: " + item.isEnabled());
+ pw.println("mIsStatic..............: " + item.isStatic());
+ pw.println("mPriority..............: " + item.mPriority);
+ pw.println("mCategory..............: " + item.mCategory);
+
+ pw.decreaseIndent();
+ pw.println("}");
+ }
+
+ private void dumpSettingsItemField(@NonNull final IndentingPrintWriter pw,
+ @NonNull final SettingsItem item, @NonNull final String field) {
+ switch (field) {
+ case "packagename":
+ pw.println(item.mPackageName);
+ break;
+ case "userid":
+ pw.println(item.mUserId);
+ break;
+ case "targetpackagename":
+ pw.println(item.mTargetPackageName);
+ break;
+ case "targetoverlayablename":
+ pw.println(item.mTargetOverlayableName);
+ break;
+ case "basecodepath":
+ pw.println(item.mBaseCodePath);
+ break;
+ case "state":
+ pw.println(OverlayInfo.stateToString(item.mState));
+ break;
+ case "isenabled":
+ pw.println(item.mIsEnabled);
+ break;
+ case "isstatic":
+ pw.println(item.mIsStatic);
+ break;
+ case "priority":
+ pw.println(item.mPriority);
+ break;
+ case "category":
+ pw.println(item.mCategory);
+ break;
}
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
index e2b1cba..7ee167a 100644
--- a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
+++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
@@ -77,13 +77,17 @@
out.println("Overlay manager (overlay) commands:");
out.println(" help");
out.println(" Print this help text.");
- out.println(" dump [--verbose] [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
+ out.println(" dump [--verbose] [--user USER_ID] [[FIELD] PACKAGE]");
out.println(" Print debugging information about the overlay manager.");
- out.println(" list [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
+ out.println(" With optional parameter PACKAGE, limit output to the specified");
+ out.println(" package. With optional parameter FIELD, limit output to");
+ out.println(" the value of that SettingsItem field. Field names are");
+ out.println(" case insensitive and out.println the m prefix can be omitted,");
+ out.println(" so the following are equivalent: mState, mstate, State, state.");
+ out.println(" list [--user USER_ID] [PACKAGE]");
out.println(" Print information about target and overlay packages.");
out.println(" Overlay packages are printed in priority order. With optional");
- out.println(" parameters PACKAGEs, limit output to the specified packages");
- out.println(" but include more information about each package.");
+ out.println(" parameter PACKAGE, limit output to the specified package.");
out.println(" enable [--user USER_ID] PACKAGE");
out.println(" Enable overlay package PACKAGE.");
out.println(" disable [--user USER_ID] PACKAGE");
@@ -116,14 +120,20 @@
return 1;
}
}
+ final String packageName = getNextArg();
final Map<String, List<OverlayInfo>> allOverlays = mInterface.getAllOverlays(userId);
for (final String targetPackageName : allOverlays.keySet()) {
- out.println(targetPackageName);
+ if (targetPackageName.equals(packageName)) {
+ out.println(targetPackageName);
+ }
List<OverlayInfo> overlaysForTarget = allOverlays.get(targetPackageName);
final int n = overlaysForTarget.size();
for (int i = 0; i < n; i++) {
final OverlayInfo oi = overlaysForTarget.get(i);
+ if (!targetPackageName.equals(packageName) && !oi.packageName.equals(packageName)) {
+ continue;
+ }
String status;
switch (oi.state) {
case OverlayInfo.STATE_ENABLED_STATIC:
@@ -139,7 +149,9 @@
}
out.println(String.format("%s %s", status, oi.packageName));
}
- out.println();
+ if (targetPackageName.equals(packageName)) {
+ out.println();
+ }
}
return 0;
}
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 497385f..dd2d300 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -22,131 +22,114 @@
import android.apex.ApexInfoList;
import android.apex.ApexSessionInfo;
import android.apex.IApexService;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException;
-import android.os.HandlerThread;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
-import android.os.SystemClock;
import android.sysprop.ApexProperties;
+import android.util.ArrayMap;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.SystemService;
import java.io.File;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.function.Function;
-import java.util.stream.Collectors;
/**
* ApexManager class handles communications with the apex service to perform operation and queries,
* as well as providing caching to avoid unnecessary calls to the service.
- *
- * @hide
*/
-public final class ApexManager extends SystemService {
- private static final String TAG = "ApexManager";
- private IApexService mApexService;
+class ApexManager {
+ static final String TAG = "ApexManager";
+ private final IApexService mApexService;
+ private final Context mContext;
+ private final Object mLock = new Object();
+ /**
+ * A map from {@code APEX packageName} to the {@Link PackageInfo} generated from the {@code
+ * AndroidManifest.xml}
+ *
+ * <p>Note that key of this map is {@code packageName} field of the corresponding {@code
+ * AndroidManfiset.xml}.
+ */
+ @GuardedBy("mLock")
+ private ArrayMap<String, PackageInfo> mActivePackagesCache;
+ /**
+ * A map from {@code apexName} to the {@Link PackageInfo} generated from the {@code
+ * AndroidManifest.xml}.
+ *
+ * <p>Note that key of this map is {@code apexName} field which corresponds to the {@code name}
+ * field of {@code apex_manifest.json}.
+ */
+ // TODO(b/132324953): remove.
+ @GuardedBy("mLock")
+ private ArrayMap<String, PackageInfo> mApexNameToPackageInfoCache;
- private final CountDownLatch mActivePackagesCacheLatch = new CountDownLatch(1);
- private Map<String, PackageInfo> mActivePackagesCache;
-
- private final CountDownLatch mApexFilesCacheLatch = new CountDownLatch(1);
- private ApexInfo[] mApexFiles;
-
- public ApexManager(Context context) {
- super(context);
- }
-
- @Override
- public void onStart() {
+ ApexManager(Context context) {
try {
mApexService = IApexService.Stub.asInterface(
- ServiceManager.getServiceOrThrow("apexservice"));
+ ServiceManager.getServiceOrThrow("apexservice"));
} catch (ServiceNotFoundException e) {
throw new IllegalStateException("Required service apexservice not available");
}
- publishLocalService(ApexManager.class, this);
- HandlerThread oneShotThread = new HandlerThread("ApexManagerOneShotHandler");
- oneShotThread.start();
- oneShotThread.getThreadHandler().post(this::initSequence);
- oneShotThread.quitSafely();
+ mContext = context;
}
- private void initSequence() {
- populateApexFilesCache();
- parseApexFiles();
+ void systemReady() {
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ onBootCompleted();
+ mContext.unregisterReceiver(this);
+ }
+ }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
}
- private void populateApexFilesCache() {
- if (mApexFiles != null) {
- return;
- }
- long startTimeMicros = SystemClock.currentTimeMicro();
- Slog.i(TAG, "Starting to populate apex files cache");
- try {
- mApexFiles = mApexService.getActivePackages();
- Slog.i(TAG, "IPC to apexd finished in " + (SystemClock.currentTimeMicro()
- - startTimeMicros) + " μs");
- } catch (RemoteException re) {
- // TODO: make sure this error is propagated to system server.
- Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
- re.rethrowAsRuntimeException();
- }
- mApexFilesCacheLatch.countDown();
- Slog.i(TAG, "Finished populating apex files cache in " + (SystemClock.currentTimeMicro()
- - startTimeMicros) + " μs");
- }
-
- private void parseApexFiles() {
- waitForLatch(mApexFilesCacheLatch);
- if (mApexFiles == null) {
- throw new IllegalStateException("mApexFiles must be populated");
- }
- long startTimeMicros = SystemClock.currentTimeMicro();
- Slog.i(TAG, "Starting to parse apex files");
- List<PackageInfo> list = new ArrayList<>();
- // TODO: this can be parallelized.
- for (ApexInfo ai : mApexFiles) {
+ private void populateActivePackagesCacheIfNeeded() {
+ synchronized (mLock) {
+ if (mActivePackagesCache != null) {
+ return;
+ }
+ mActivePackagesCache = new ArrayMap<>();
+ mApexNameToPackageInfoCache = new ArrayMap<>();
try {
- // If the device is using flattened APEX, don't report any APEX
- // packages since they won't be managed or updated by PackageManager.
- if ((new File(ai.packagePath)).isDirectory()) {
- break;
+ final ApexInfo[] activePkgs = mApexService.getActivePackages();
+ for (ApexInfo ai : activePkgs) {
+ // If the device is using flattened APEX, don't report any APEX
+ // packages since they won't be managed or updated by PackageManager.
+ if ((new File(ai.packagePath)).isDirectory()) {
+ break;
+ }
+ try {
+ final PackageInfo pkg = PackageParser.generatePackageInfoFromApex(
+ new File(ai.packagePath), PackageManager.GET_META_DATA
+ | PackageManager.GET_SIGNING_CERTIFICATES);
+ mActivePackagesCache.put(pkg.packageName, pkg);
+ // TODO(b/132324953): remove.
+ mApexNameToPackageInfoCache.put(ai.packageName, pkg);
+ } catch (PackageParserException pe) {
+ throw new IllegalStateException("Unable to parse: " + ai, pe);
+ }
}
- list.add(PackageParser.generatePackageInfoFromApex(
- new File(ai.packagePath), PackageManager.GET_META_DATA
- | PackageManager.GET_SIGNING_CERTIFICATES));
- } catch (PackageParserException pe) {
- // TODO: make sure this error is propagated to system server.
- throw new IllegalStateException("Unable to parse: " + ai, pe);
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
+ throw new RuntimeException(re);
}
}
- mActivePackagesCache = list.stream().collect(
- Collectors.toMap(p -> p.packageName, Function.identity()));
- mActivePackagesCacheLatch.countDown();
- Slog.i(TAG, "Finished parsing apex files in " + (SystemClock.currentTimeMicro()
- - startTimeMicros) + " μs");
}
/**
* Retrieves information about an active APEX package.
*
- * <p>This method blocks caller thread until {@link #parseApexFiles()} succeeds. Note that in
- * case {@link #parseApexFiles()}} throws an exception this method will never finish
- * essentially putting device into a boot loop.
- *
* @param packageName the package name to look for. Note that this is the package name reported
* in the APK container manifest (i.e. AndroidManifest.xml), which might
* differ from the one reported in the APEX manifest (i.e.
@@ -155,43 +138,42 @@
* is not found.
*/
@Nullable PackageInfo getActivePackage(String packageName) {
- waitForLatch(mActivePackagesCacheLatch);
+ populateActivePackagesCacheIfNeeded();
return mActivePackagesCache.get(packageName);
}
/**
+ * Returns a {@link PackageInfo} for an APEX package keyed by it's {@code apexName}.
+ *
+ * @deprecated this API will soon be deleted, please don't depend on it.
+ */
+ // TODO(b/132324953): delete.
+ @Deprecated
+ @Nullable PackageInfo getPackageInfoForApexName(String apexName) {
+ populateActivePackagesCacheIfNeeded();
+ return mApexNameToPackageInfoCache.get(apexName);
+ }
+
+ /**
* Retrieves information about all active APEX packages.
*
- * <p>This method blocks caller thread until {@link #parseApexFiles()} succeeds. Note that in
- * case {@link #parseApexFiles()}} throws an exception this method will never finish
- * essentially putting device into a boot loop.
- *
* @return a Collection of PackageInfo object, each one containing information about a different
* active package.
*/
Collection<PackageInfo> getActivePackages() {
- waitForLatch(mActivePackagesCacheLatch);
+ populateActivePackagesCacheIfNeeded();
return mActivePackagesCache.values();
}
/**
* Checks if {@code packageName} is an apex package.
*
- * <p>This method blocks caller thread until {@link #populateApexFilesCache()} succeeds. Note
- * that in case {@link #populateApexFilesCache()} throws an exception this method will never
- * finish essentially putting device into a boot loop.
- *
* @param packageName package to check.
* @return {@code true} if {@code packageName} is an apex package.
*/
boolean isApexPackage(String packageName) {
- waitForLatch(mApexFilesCacheLatch);
- for (ApexInfo ai : mApexFiles) {
- if (ai.packageName.equals(packageName)) {
- return true;
- }
- }
- return false;
+ populateActivePackagesCacheIfNeeded();
+ return mActivePackagesCache.containsKey(packageName);
}
/**
@@ -319,19 +301,6 @@
}
/**
- * Blocks current thread until {@code latch} has counted down to zero.
- *
- * @throws RuntimeException if thread was interrupted while waiting.
- */
- private void waitForLatch(CountDownLatch latch) {
- try {
- latch.await();
- } catch (InterruptedException e) {
- throw new RuntimeException("Interrupted waiting for cache to be populated", e);
- }
- }
-
- /**
* Dumps various state information to the provided {@link PrintWriter} object.
*
* @param pw the {@link PrintWriter} object to send information to.
@@ -344,7 +313,7 @@
ipw.println("Active APEX packages:");
ipw.increaseIndent();
try {
- waitForLatch(mActivePackagesCacheLatch);
+ populateActivePackagesCacheIfNeeded();
for (PackageInfo pi : mActivePackagesCache.values()) {
if (packageName != null && !packageName.equals(pi.packageName)) {
continue;
@@ -389,4 +358,8 @@
ipw.println("Couldn't communicate with apexd.");
}
}
+
+ public void onBootCompleted() {
+ populateActivePackagesCacheIfNeeded();
+ }
}
diff --git a/services/core/java/com/android/server/pm/DumpState.java b/services/core/java/com/android/server/pm/DumpState.java
index 89895c5..d473fbf 100644
--- a/services/core/java/com/android/server/pm/DumpState.java
+++ b/services/core/java/com/android/server/pm/DumpState.java
@@ -45,6 +45,7 @@
public static final int OPTION_SHOW_FILTERS = 1 << 0;
public static final int OPTION_DUMP_ALL_COMPONENTS = 1 << 1;
+ public static final int OPTION_SKIP_PERMISSIONS = 1 << 2;
private int mTypes;
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index bab612d..9d11596 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -73,6 +73,7 @@
public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE;
public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE;
+ public static final int FLAG_STORAGE_EXTERNAL = IInstalld.FLAG_STORAGE_EXTERNAL;
public static final int FLAG_CLEAR_CACHE_ONLY = IInstalld.FLAG_CLEAR_CACHE_ONLY;
public static final int FLAG_CLEAR_CODE_CACHE_ONLY = IInstalld.FLAG_CLEAR_CODE_CACHE_ONLY;
diff --git a/services/core/java/com/android/server/pm/ModuleInfoProvider.java b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
index e7dace0..691b38e2b 100644
--- a/services/core/java/com/android/server/pm/ModuleInfoProvider.java
+++ b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
@@ -28,6 +28,7 @@
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.R;
@@ -39,6 +40,7 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -165,7 +167,27 @@
throw new IllegalStateException("Call to getInstalledModules before metadata loaded");
}
- return new ArrayList<>(mModuleInfo.values());
+ ArrayList<ModuleInfo> allModules = new ArrayList<>(mModuleInfo.values());
+ if ((flags & PackageManager.MATCH_ALL) != 0) {
+ return allModules;
+ }
+
+ ArraySet<String> allPackages;
+ try {
+ allPackages = new ArraySet<>(mPackageManager.getAllPackages());
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Unable to retrieve all package names", e);
+ return Collections.emptyList();
+ }
+
+ ArrayList<ModuleInfo> installedModules = new ArrayList<>(allPackages.size());
+ for (int i = allModules.size() - 1; i >= 0; --i) {
+ ModuleInfo mi = allModules.get(i);
+ if (allPackages.contains(mi.getPackageName())) {
+ installedModules.add(mi);
+ }
+ }
+ return installedModules;
}
ModuleInfo getModuleInfo(String packageName, int flags) {
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 7f346f5..6594751 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -506,15 +506,27 @@
*/
private String getRealCompilerFilter(ApplicationInfo info, String targetCompilerFilter,
boolean isUsedByOtherApps) {
- int flags = info.flags;
- boolean vmSafeMode = (flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0;
// When an app or priv app is configured to run out of box, only verify it.
if (info.isEmbeddedDexUsed()
|| (info.isPrivilegedApp()
&& DexManager.isPackageSelectedToRunOob(info.packageName))) {
return "verify";
}
- if (vmSafeMode) {
+
+ // We force vmSafeMode on debuggable apps as well:
+ // - the runtime ignores their compiled code
+ // - they generally have lots of methods that could make the compiler used run
+ // out of memory (b/130828957)
+ // Note that forcing the compiler filter here applies to all compilations (even if they
+ // are done via adb shell commands). That's ok because right now the runtime will ignore
+ // the compiled code anyway. The alternative would have been to update either
+ // PackageDexOptimizer#canOptimizePackage or PackageManagerService#getOptimizablePackages
+ // but that would have the downside of possibly producing a big odex files which would
+ // be ignored anyway.
+ boolean vmSafeModeOrDebuggable = ((info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0)
+ || ((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
+
+ if (vmSafeModeOrDebuggable) {
return getSafeModeCompilerFilter(targetCompilerFilter);
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index e6313d9..35f2149 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -531,16 +531,6 @@
+ "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
}
- // Only system components can circumvent restricted whitelisting when installing.
- if ((params.installFlags
- & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0
- && mContext.checkCallingOrSelfPermission(Manifest.permission
- .WHITELIST_RESTRICTED_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {
- throw new SecurityException("You need the "
- + "android.permission.WHITELIST_RESTRICTED_PERMISSIONS permission to"
- + " use the PackageManager.INSTALL_WHITELIST_RESTRICTED_PERMISSIONS flag");
- }
-
// Defensively resize giant app icons
if (params.appIcon != null) {
final ActivityManager am = (ActivityManager) mContext.getSystemService(
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5f6e739..6f9a918 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1150,7 +1150,7 @@
*/
void sealAndValidateIfNecessary() {
synchronized (mLock) {
- if (!mShouldBeSealed) {
+ if (!mShouldBeSealed || isStagedAndInTerminalState()) {
return;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6f8439b..23aa8f0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -89,6 +89,7 @@
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
+import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
@@ -939,7 +940,6 @@
ComponentName mCustomResolverComponentName;
boolean mResolverReplaced = false;
- boolean mOkToReplacePersistentPackages = false;
private final @Nullable ComponentName mIntentFilterVerifierComponent;
private final @Nullable IntentFilterVerifier<ActivityIntentInfo> mIntentFilterVerifier;
@@ -1009,6 +1009,9 @@
private PackageManagerInternal.DefaultBrowserProvider mDefaultBrowserProvider;
@GuardedBy("mPackages")
+ private PackageManagerInternal.DefaultDialerProvider mDefaultDialerProvider;
+
+ @GuardedBy("mPackages")
private PackageManagerInternal.DefaultHomeProvider mDefaultHomeProvider;
private class IntentVerifierProxy implements IntentFilterVerifier<ActivityIntentInfo> {
@@ -1744,6 +1747,15 @@
Trace.asyncTraceEnd(
TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken);
params.handleRollbackEnabled();
+ Intent rollbackTimeoutIntent = new Intent(
+ Intent.ACTION_CANCEL_ENABLE_ROLLBACK);
+ rollbackTimeoutIntent.putExtra(
+ PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN,
+ enableRollbackToken);
+ rollbackTimeoutIntent.addFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mContext.sendBroadcastAsUser(rollbackTimeoutIntent, UserHandle.SYSTEM,
+ android.Manifest.permission.PACKAGE_ROLLBACK_AGENT);
}
break;
}
@@ -2375,8 +2387,6 @@
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
- mApexManager = LocalServices.getService(ApexManager.class);
-
LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "create package manager");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
@@ -2473,6 +2483,7 @@
mProtectedPackages = new ProtectedPackages(mContext);
+ mApexManager = new ApexManager(context);
synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
@@ -3239,7 +3250,7 @@
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
// No apps are running this early, so no need to freeze
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
+ FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
}
@@ -3492,8 +3503,8 @@
}
return false;
}
- clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE
- | FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
+ | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
mDexManager.notifyPackageUpdated(pkg.packageName,
pkg.baseCodePath, pkg.splitCodePaths);
}
@@ -5638,6 +5649,27 @@
final PackageParser.Package pkg = (packageNames != null && packageNames.length > 0)
? mPackages.get(packageNames[0])
: null;
+ // Additional logs for b/111075456; ignore system UIDs
+ if (pkg == null && UserHandle.getAppId(uid) >= Process.FIRST_APPLICATION_UID) {
+ if (packageNames == null || packageNames.length < 2) {
+ // unclear if this is shared user or just a missing application
+ Log.e(TAG, "Failed to find package"
+ + "; permName: " + permName
+ + ", uid: " + uid
+ + ", caller: " + Binder.getCallingUid(),
+ new Throwable());
+ } else {
+ // definitely shared user
+ Log.e(TAG, "Failed to find package"
+ + "; permName: " + permName
+ + ", uid: " + uid
+ + ", caller: " + Binder.getCallingUid()
+ + ", packages: " + Arrays.toString(packageNames),
+ new Throwable());
+ }
+ // run again just to try to get debug output
+ getPackagesForUid_debug(uid, true);
+ }
return mPermissionManager.checkUidPermission(permName, pkg, uid, getCallingUid());
}
}
@@ -6355,15 +6387,25 @@
@Override
public String[] getPackagesForUid(int uid) {
+ return getPackagesForUid_debug(uid, false);
+ }
+ // Debug output for b/111075456
+ private String[] getPackagesForUid_debug(int uid, boolean debug) {
final int callingUid = Binder.getCallingUid();
final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
final int userId = UserHandle.getUserId(uid);
final int appId = UserHandle.getAppId(uid);
+ if (debug) Slog.e(TAG, "Finding packages for UID"
+ + "; uid: " + uid
+ + ", userId: " + userId
+ + ", appId: " + appId
+ + ", caller: " + callingUid);
// reader
synchronized (mPackages) {
final Object obj = mSettings.getSettingLPr(appId);
if (obj instanceof SharedUserSetting) {
if (isCallerInstantApp) {
+ if (debug) Slog.e(TAG, "Caller is instant and package has shared users");
return null;
}
final SharedUserSetting sus = (SharedUserSetting) obj;
@@ -6371,8 +6413,13 @@
String[] res = new String[N];
final Iterator<PackageSetting> it = sus.packages.iterator();
int i = 0;
+ if (debug && !it.hasNext()) Slog.e(TAG, "Shared user, but, no packages");
while (it.hasNext()) {
PackageSetting ps = it.next();
+ if (debug) Slog.e(TAG, "Check shared package"
+ + "; installed? " + ps.getInstalled(userId)
+ + ", shared setting: " + ps
+ + ", package setting: " + mSettings.mPackages.get(ps.name));
if (ps.getInstalled(userId)) {
res[i++] = ps.name;
} else {
@@ -6385,6 +6432,12 @@
if (ps.getInstalled(userId) && !filterAppAccessLPr(ps, callingUid, userId)) {
return new String[]{ps.name};
}
+ if (debug) Slog.e(TAG, "Removing normal package"
+ + "; installed? " + ps.getInstalled(userId)
+ + ", filtered? " + filterAppAccessLPr(ps, callingUid, userId));
+ } else if (debug) {
+ if (debug) Slog.e(TAG, "No setting found"
+ + "; obj: " + (obj == null ? "<<NULL>>" : obj.toString()));
}
}
return null;
@@ -10338,31 +10391,6 @@
} catch (InstallerException e) {
Slog.w(TAG, String.valueOf(e));
}
- // If this package doesn't have a sharedUserId or there are no other packages
- // present with same sharedUserId, then delete the sandbox data too.
- try {
- final SharedUserSetting sharedUserSetting = mSettings.getSharedUserLPw(
- pkg.mSharedUserId, 0 /* pkgFlags */,
- 0 /* pkgPrivateFlags */, false /* create */);
- boolean deleteSandboxData = true;
- if (sharedUserSetting != null && sharedUserSetting.packages != null) {
- for (int i = sharedUserSetting.packages.size() - 1; i >= 0; --i) {
- final PackageSetting packageSetting = sharedUserSetting.packages.valueAt(i);
- if (!packageSetting.name.equals(pkg.packageName)
- && packageSetting.readUserState(realUserId).isAvailable(
- MATCH_UNINSTALLED_PACKAGES)) {
- deleteSandboxData = false;
- break;
- }
- }
- }
- if (deleteSandboxData && getStorageManagerInternal() != null) {
- getStorageManagerInternal().destroySandboxForApp(pkg.packageName,
- pkg.mSharedUserId, realUserId);
- }
- } catch (PackageManagerException e) {
- // Should not happen
- }
mDexManager.notifyPackageDataDestroyed(pkg.packageName, userId);
}
}
@@ -11726,7 +11754,12 @@
"Code and resource paths haven't been set correctly");
}
- if (mApexManager.isApexPackage(pkg.packageName)) {
+ // Check that there is an APEX package with the same name only during install/first boot
+ // after OTA.
+ final boolean isUserInstall = (scanFlags & SCAN_BOOTING) == 0;
+ final boolean isFirstBootOrUpgrade = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0;
+ if ((isUserInstall || isFirstBootOrUpgrade)
+ && mApexManager.isApexPackage(pkg.packageName)) {
throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
pkg.packageName + " is an APEX package and can't be installed as an APK.");
}
@@ -13663,30 +13696,44 @@
return unactionedPackages.toArray(new String[0]);
}
- @Override
- public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
- PersistableBundle appExtras, PersistableBundle launcherExtras,
- SuspendDialogInfo dialogInfo, String callingPackage, int userId) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS,
- "setPackagesSuspendedAsUser");
+ private void enforceCanSetPackagesSuspendedAsUser(String callingPackage, int callingUid,
+ int userId, String callingMethod) {
+ if (callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID) {
+ return;
+ }
- final int callingUid = Binder.getCallingUid();
+ final String ownerPackage = mProtectedPackages.getDeviceOwnerOrProfileOwnerPackage(userId);
+ if (ownerPackage != null) {
+ final int ownerUid = getPackageUid(ownerPackage, 0, userId);
+ if (ownerUid == callingUid) {
+ return;
+ }
+ throw new UnsupportedOperationException("Cannot suspend/unsuspend packages. User "
+ + userId + " has an active DO or PO");
+ }
+
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS,
+ callingMethod);
+
final int packageUid = getPackageUid(callingPackage, 0, userId);
- final boolean allowedCallingUid = callingUid == Process.ROOT_UID
- || callingUid == Process.SYSTEM_UID;
final boolean allowedPackageUid = packageUid == callingUid;
final boolean allowedShell = callingUid == SHELL_UID
&& UserHandle.isSameApp(packageUid, callingUid);
- if (!allowedCallingUid && !allowedShell && !allowedPackageUid) {
+ if (!allowedShell && !allowedPackageUid) {
throw new SecurityException("Calling package " + callingPackage + " in user "
+ userId + " does not belong to calling uid " + callingUid);
}
- if (!PLATFORM_PACKAGE_NAME.equals(callingPackage)
- && mProtectedPackages.getDeviceOwnerOrProfileOwnerPackage(userId) != null) {
- throw new UnsupportedOperationException("Cannot suspend/unsuspend packages. User "
- + userId + " has an active DO or PO");
- }
+ }
+
+ @Override
+ public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
+ PersistableBundle appExtras, PersistableBundle launcherExtras,
+ SuspendDialogInfo dialogInfo, String callingPackage, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ enforceCanSetPackagesSuspendedAsUser(callingPackage, callingUid, userId,
+ "setPackagesSuspendedAsUser");
+
if (ArrayUtils.isEmpty(packageNames)) {
return packageNames;
}
@@ -13984,10 +14031,17 @@
return resolveInfo == null ? null : resolveInfo.activityInfo.packageName;
}
- private String getDefaultDialerPackageName(int userId) {
+ @Nullable
+ private String getDefaultDialerPackageName(@UserIdInt int userId) {
+ PackageManagerInternal.DefaultDialerProvider provider;
synchronized (mPackages) {
- return mSettings.getDefaultDialerPackageNameLPw(userId);
+ provider = mDefaultDialerProvider;
}
+ if (provider == null) {
+ Slog.e(TAG, "mDefaultDialerProvider is null");
+ return null;
+ }
+ return provider.getDefaultDialer(userId);
}
@Override
@@ -14996,12 +15050,14 @@
final int installReason;
@Nullable
MultiPackageInstallParams mParentInstallParams;
+ final long requiredInstalledVersionCode;
InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, String volumeUuid,
VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
- PackageParser.SigningDetails signingDetails, int installReason) {
+ PackageParser.SigningDetails signingDetails, int installReason,
+ long requiredInstalledVersionCode) {
super(user);
this.origin = origin;
this.move = move;
@@ -15015,6 +15071,7 @@
this.whitelistedRestrictedPermissions = whitelistedRestrictedPermissions;
this.signingDetails = signingDetails;
this.installReason = installReason;
+ this.requiredInstalledVersionCode = requiredInstalledVersionCode;
}
InstallParams(ActiveInstallSession activeInstallSession) {
@@ -15045,6 +15102,8 @@
whitelistedRestrictedPermissions = activeInstallSession.getSessionParams()
.whitelistedRestrictedPermissions;
signingDetails = activeInstallSession.getSigningDetails();
+ requiredInstalledVersionCode = activeInstallSession.getSessionParams()
+ .requiredInstalledVersionCode;
}
@Override
@@ -15073,6 +15132,23 @@
}
}
+ if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST) {
+ if (dataOwnerPkg == null) {
+ Slog.w(TAG, "Required installed version code was "
+ + requiredInstalledVersionCode
+ + " but package is not installed");
+ return PackageHelper.RECOMMEND_FAILED_WRONG_INSTALLED_VERSION;
+ }
+
+ if (dataOwnerPkg.getLongVersionCode() != requiredInstalledVersionCode) {
+ Slog.w(TAG, "Required installed version code was "
+ + requiredInstalledVersionCode
+ + " but actual installed version is "
+ + dataOwnerPkg.getLongVersionCode());
+ return PackageHelper.RECOMMEND_FAILED_WRONG_INSTALLED_VERSION;
+ }
+ }
+
if (dataOwnerPkg != null) {
if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
dataOwnerPkg.applicationInfo.flags)) {
@@ -15199,6 +15275,8 @@
loc = installLocationPolicy(pkgLite);
if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
+ } else if (loc == PackageHelper.RECOMMEND_FAILED_WRONG_INSTALLED_VERSION) {
+ ret = PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION;
} else if (!onInt) {
// Override install location with flags
if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
@@ -15898,6 +15976,9 @@
synchronized (mInstallLock) {
// Clean up both app data and code
// All package moves are frozen until finished
+
+ // We purposefully exclude FLAG_STORAGE_EXTERNAL here, since
+ // this task was only focused on moving data on internal storage.
for (int userId : userIds) {
try {
mInstaller.destroyAppData(volumeUuid, move.packageName, userId,
@@ -16998,8 +17079,8 @@
final String packageName = pkg.packageName;
prepareAppDataAfterInstallLIF(pkg);
if (reconciledPkg.prepareResult.clearCodeCache) {
- clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE
- | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
+ | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
if (reconciledPkg.prepareResult.replace) {
mDexManager.notifyPackageUpdated(pkg.packageName,
@@ -17349,7 +17430,7 @@
}
// Prevent persistent apps from being updated
if (((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0)
- && !mOkToReplacePersistentPackages) {
+ && ((installFlags & PackageManager.INSTALL_STAGED) == 0)) {
throw new PrepareFailure(PackageManager.INSTALL_FAILED_INVALID_APK,
"Package " + oldPackage.packageName + " is a persistent app. "
+ "Persistent apps are not updateable.");
@@ -18771,7 +18852,7 @@
resolvedPkg.setVolumeUuid(deletedPs.volumeUuid);
}
destroyAppDataLIF(resolvedPkg, UserHandle.USER_ALL,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+ FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
destroyAppProfilesLIF(resolvedPkg);
if (outInfo != null) {
outInfo.dataRemoved = true;
@@ -19523,7 +19604,7 @@
}
destroyAppDataLIF(pkg, nextUserId,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+ FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
clearDefaultBrowserIfNeededForUser(ps.name, nextUserId);
removeKeystoreDataIfNeeded(nextUserId, ps.appId);
final SparseBooleanArray changedUsers = new SparseBooleanArray();
@@ -19659,7 +19740,7 @@
}
clearAppDataLIF(pkg, userId,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+ FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
removeKeystoreDataIfNeeded(userId, appId);
@@ -19890,8 +19971,7 @@
}
if (doClearData) {
synchronized (mInstallLock) {
- final int flags = StorageManager.FLAG_STORAGE_DE
- | StorageManager.FLAG_STORAGE_CE;
+ final int flags = FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL;
// We're only clearing cache files, so we don't care if the
// app is unfrozen and still able to run
clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
@@ -20019,14 +20099,14 @@
+ userId + ":");
filter.dump(new LogPrinter(Log.INFO, TAG), " ");
}
- if (!updateDefaultHomeNotLocked(userId)) {
- postPreferredActivityChangedBroadcast(userId);
- }
synchronized (mPackages) {
final PreferredIntentResolver pir = mSettings.editPreferredActivitiesLPw(userId);
pir.addFilter(new PreferredActivity(filter, match, set, activity, always));
scheduleWritePackageRestrictionsLocked(userId);
}
+ if (!updateDefaultHomeNotLocked(userId)) {
+ postPreferredActivityChangedBroadcast(userId);
+ }
}
private void postPreferredActivityChangedBroadcast(int userId) {
@@ -20038,6 +20118,7 @@
final Intent intent = new Intent(Intent.ACTION_PREFERRED_ACTIVITY_CHANGED);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
try {
am.broadcastIntent(null, intent, null, null,
0, null, null, null, android.app.AppOpsManager.OP_NONE,
@@ -20340,13 +20421,13 @@
+ " for user " + userId + ":");
filter.dump(new LogPrinter(Log.INFO, TAG), " ");
}
- updateDefaultHomeNotLocked(userId);
- postPreferredActivityChangedBroadcast(userId);
synchronized (mPackages) {
mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter(
new PersistentPreferredActivity(filter, activity));
scheduleWritePackageRestrictionsLocked(userId);
}
+ updateDefaultHomeNotLocked(userId);
+ postPreferredActivityChangedBroadcast(userId);
}
@Override
@@ -21323,6 +21404,10 @@
if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
return null;
}
+ // InstallerPackageName for Apex is not stored in PackageManager
+ if (ps == null && mApexManager.isApexPackage(packageName)) {
+ return null;
+ }
return mSettings.getInstallerPackageNameLPr(packageName);
}
}
@@ -21487,6 +21572,7 @@
storage.registerListener(mStorageListener);
mInstallerService.systemReady();
+ mApexManager.systemReady();
mPackageDexOptimizer.systemReady();
getStorageManagerInternal().addExternalStoragePolicy(
@@ -21529,12 +21615,10 @@
mModuleInfoProvider.systemReady();
- mOkToReplacePersistentPackages = true;
// Installer service might attempt to install some packages that have been staged for
// installation on reboot. Make sure this is the last component to be call since the
// installation might require other components to be ready.
mInstallerService.restoreAndApplyStagedSessionIfNeeded();
- mOkToReplacePersistentPackages = false;
}
public void waitForAppDataPrepared() {
@@ -21743,6 +21827,9 @@
dumpState.setDump(DumpState.DUMP_PACKAGES);
} else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_SHARED_USERS);
+ if (opti < args.length && "noperm".equals(args[opti])) {
+ dumpState.setOptionEnabled(DumpState.OPTION_SKIP_PERMISSIONS);
+ }
} else if ("prov".equals(cmd) || "providers".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_PROVIDERS);
} else if ("m".equals(cmd) || "messages".equals(cmd)) {
@@ -22432,9 +22519,8 @@
}
if (!Build.FINGERPRINT.equals(ver.fingerprint)) {
- clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
- | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ clearAppDataLIF(ps.pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
+ | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
}
}
@@ -22889,10 +22975,6 @@
}
prepareAppDataContentsLeafLIF(pkg, userId, flags);
- if (getStorageManagerInternal() != null) {
- getStorageManagerInternal().prepareSandboxForApp(
- pkg.packageName, appId, pkg.mSharedUserId, userId);
- }
}
private void prepareAppDataContentsLIF(PackageParser.Package pkg, int userId, int flags) {
@@ -23311,7 +23393,7 @@
installerPackageName, volumeUuid, null /*verificationInfo*/, user,
packageAbiOverride, null /*grantedPermissions*/,
null /*whitelistedRestrictedPermissions*/, PackageParser.SigningDetails.UNKNOWN,
- PackageManager.INSTALL_REASON_UNKNOWN);
+ PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.VERSION_CODE_HIGHEST);
params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -23937,6 +24019,18 @@
}
@Override
+ public int getTargetSdkVersionForPackage(String packageName)
+ throws RemoteException {
+ int callingUser = UserHandle.getUserId(Binder.getCallingUid());
+ ApplicationInfo info = getApplicationInfo(packageName, 0, callingUser);
+ if (info == null) {
+ throw new RemoteException(
+ "Couldn't get ApplicationInfo for package " + packageName);
+ }
+ return info.targetSdkVersion;
+ }
+
+ @Override
public boolean[] isAudioPlaybackCaptureAllowed(String[] packageNames)
throws RemoteException {
int callingUser = UserHandle.getUserId(Binder.getCallingUid());
@@ -24184,13 +24278,6 @@
}
@Override
- public void onDefaultDialerAppChanged(String packageName, int userId) {
- synchronized (mPackages) {
- mSettings.setDefaultDialerPackageNameLPw(packageName, userId);
- }
- }
-
- @Override
public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) {
mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultUseOpenWifiApp(
packageName, userId);
@@ -24736,6 +24823,13 @@
}
@Override
+ public void setDefaultDialerProvider(@NonNull DefaultDialerProvider provider) {
+ synchronized (mPackages) {
+ mDefaultDialerProvider = provider;
+ }
+ }
+
+ @Override
public void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider) {
synchronized (mPackages) {
mDefaultHomeProvider = provider;
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 33dd48a..d9a608d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -39,6 +39,7 @@
import android.content.pm.IPackageInstaller;
import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
+import android.content.pm.ModuleInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
@@ -273,6 +274,8 @@
return uninstallSystemUpdates();
case "rollback-app":
return runRollbackApp();
+ case "get-moduleinfo":
+ return runGetModuleInfo();
default: {
String nextArg = getNextArg();
if (nextArg == null) {
@@ -295,6 +298,49 @@
return -1;
}
+ /**
+ * Shows module info
+ *
+ * Usage: get-moduleinfo [--all | --installed] [module-name]
+ * Example: get-moduleinfo, get-moduleinfo --all, get-moduleinfo xyz
+ */
+ private int runGetModuleInfo() {
+ final PrintWriter pw = getOutPrintWriter();
+ int flags = 0;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "--all":
+ flags |= PackageManager.MATCH_ALL;
+ break;
+ case "--installed":
+ break;
+ default:
+ pw.println("Error: Unknown option: " + opt);
+ return -1;
+ }
+ }
+
+ String moduleName = getNextArg();
+ try {
+ if (moduleName != null) {
+ ModuleInfo m = mInterface.getModuleInfo(moduleName, flags);
+ pw.println(m.toString() + " packageName: " + m.getPackageName());
+
+ } else {
+ List<ModuleInfo> modules = mInterface.getInstalledModules(flags);
+ for (ModuleInfo m: modules) {
+ pw.println(m.toString() + " packageName: " + m.getPackageName());
+ }
+ }
+ } catch (RemoteException e) {
+ pw.println("Failure [" + e.getClass().getName() + " - " + e.getMessage() + "]");
+ return -1;
+ }
+ return 1;
+ }
+
private int getStagedSessions() {
final PrintWriter pw = getOutPrintWriter();
try {
@@ -723,7 +769,7 @@
pw.print(info.getLongVersionCode());
}
}
- if (listInstaller && !isApex) {
+ if (listInstaller) {
pw.print(" installer=");
pw.print(mInterface.getInstallerPackageName(info.packageName));
}
@@ -2351,9 +2397,10 @@
break;
case "-g":
sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
- case "-w":
- sessionParams.installFlags |=
- PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
+ break;
+ case "--restrict-permissions":
+ sessionParams.installFlags &=
+ ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
break;
case "--dont-kill":
sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
@@ -3004,10 +3051,10 @@
pw.println(" -d: allow version code downgrade (debuggable packages only)");
pw.println(" -p: partial application install (new split on top of existing pkg)");
pw.println(" -g: grant all runtime permissions");
- pw.println(" -w: whitelist all restricted permissions");
pw.println(" -S: size in bytes of package, required for stdin");
pw.println(" --user: install under the given user.");
pw.println(" --dont-kill: installing a new feature split, don't kill running app");
+ pw.println(" --restrict-permissions: don't whitelist restricted permissions at install");
pw.println(" --originating-uri: set URI where app was downloaded from");
pw.println(" --referrer: set URI that instigated the install of the app");
pw.println(" --pkg: specify expected package name of app being installed");
@@ -3204,6 +3251,12 @@
pw.println(" Remove updates to all system applications and fall back to their /system " +
"version.");
pw.println();
+ pw.println(" get-moduleinfo [--all | --installed] [module-name]");
+ pw.println(" Displays module info. If module-name is specified only that info is shown");
+ pw.println(" By default, without any argument only installed modules are shown.");
+ pw.println(" --all: show all module info");
+ pw.println(" --installed: show only installed modules");
+ pw.println("");
Intent.printIntentArgsHelp(pw , "");
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 2a9cb89..a723313 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -362,9 +362,6 @@
// For every user, it is used to find the package name of the default Browser App.
final SparseArray<String> mDefaultBrowserApp = new SparseArray<String>();
- // For every user, a record of the package name of the default Dialer App.
- final SparseArray<String> mDefaultDialerApp = new SparseArray<String>();
-
// App-link priority tracking, per-user
final SparseIntArray mNextAppLinkGeneration = new SparseIntArray();
@@ -1270,19 +1267,6 @@
return (userId == UserHandle.USER_ALL) ? null : mDefaultBrowserApp.removeReturnOld(userId);
}
- boolean setDefaultDialerPackageNameLPw(String packageName, int userId) {
- if (userId == UserHandle.USER_ALL) {
- return false;
- }
- mDefaultDialerApp.put(userId, packageName);
- writePackageRestrictionsLPr(userId);
- return true;
- }
-
- String getDefaultDialerPackageNameLPw(int userId) {
- return (userId == UserHandle.USER_ALL) ? null : mDefaultDialerApp.get(userId);
- }
-
private File getUserPackagesStateFile(int userId) {
// TODO: Implement a cleaner solution when adding tests.
// This instead of Environment.getUserSystemDirectory(userId) to support testing.
@@ -1482,8 +1466,7 @@
String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
mDefaultBrowserApp.put(userId, packageName);
} else if (tagName.equals(TAG_DEFAULT_DIALER)) {
- String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
- mDefaultDialerApp.put(userId, packageName);
+ // Ignored.
} else {
String msg = "Unknown element under " + TAG_DEFAULT_APPS + ": " +
parser.getName();
@@ -1938,12 +1921,6 @@
serializer.attribute(null, ATTR_PACKAGE_NAME, defaultBrowser);
serializer.endTag(null, TAG_DEFAULT_BROWSER);
}
- String defaultDialer = mDefaultDialerApp.get(userId);
- if (!TextUtils.isEmpty(defaultDialer)) {
- serializer.startTag(null, TAG_DEFAULT_DIALER);
- serializer.attribute(null, ATTR_PACKAGE_NAME, defaultDialer);
- serializer.endTag(null, TAG_DEFAULT_DIALER);
- }
serializer.endTag(null, TAG_DEFAULT_APPS);
}
@@ -2575,10 +2552,6 @@
writeKernelMappingLPr(ps);
}
- for (final SharedUserSetting sus : mSharedUsers.values()) {
- knownSet.remove(sus.getStorageSandboxName());
- }
-
// Remove any unclaimed mappings
for (int i = 0; i < knownSet.size(); i++) {
final String name = knownSet.valueAt(i);
@@ -2589,20 +2562,10 @@
}
}
- void writeKernelMappingLPr(SharedUserSetting sus) {
- if (mKernelMappingFilename == null || sus == null || sus.name == null) return;
-
- writeKernelMappingLPr(sus.getStorageSandboxName(),
- sus.userId, sus.getNotInstalledUserIds());
- }
-
void writeKernelMappingLPr(PackageSetting ps) {
if (mKernelMappingFilename == null || ps == null || ps.name == null) return;
writeKernelMappingLPr(ps.name, ps.appId, ps.getNotInstalledUserIds());
- if (ps.sharedUser != null) {
- writeKernelMappingLPr(ps.sharedUser);
- }
}
void writeKernelMappingLPr(String name, int appId, int[] excludedUserIds) {
@@ -4959,27 +4922,43 @@
pw.println("Shared users:");
printedSomething = true;
}
+
pw.print(" SharedUser [");
pw.print(su.name);
pw.print("] (");
pw.print(Integer.toHexString(System.identityHashCode(su)));
- pw.println("):");
+ pw.println("):");
String prefix = " ";
pw.print(prefix); pw.print("userId="); pw.println(su.userId);
- PermissionsState permissionsState = su.getPermissionsState();
+ pw.print(prefix); pw.println("Packages");
+ final int numPackages = su.packages.size();
+ for (int i = 0; i < numPackages; i++) {
+ final PackageSetting ps = su.packages.valueAt(i);
+ if (ps != null) {
+ pw.print(prefix + " "); pw.println(ps.toString());
+ } else {
+ pw.print(prefix + " "); pw.println("NULL?!");
+ }
+ }
+
+ if (dumpState.isOptionEnabled(DumpState.OPTION_SKIP_PERMISSIONS)) {
+ continue;
+ }
+
+ final PermissionsState permissionsState = su.getPermissionsState();
dumpInstallPermissionsLPr(pw, prefix, permissionNames, permissionsState);
for (int userId : UserManagerService.getInstance().getUserIds()) {
final int[] gids = permissionsState.computeGids(userId);
- List<PermissionState> permissions = permissionsState
- .getRuntimePermissionStates(userId);
+ final List<PermissionState> permissions =
+ permissionsState.getRuntimePermissionStates(userId);
if (!ArrayUtils.isEmpty(gids) || !permissions.isEmpty()) {
pw.print(prefix); pw.print("User "); pw.print(userId); pw.println(": ");
dumpGidsLPr(pw, prefix + " ", gids);
- dumpRuntimePermissionsLPr(pw, prefix + " ", permissionNames, permissions,
- packageName != null);
+ dumpRuntimePermissionsLPr(pw, prefix + " ", permissionNames,
+ permissions, packageName != null);
}
}
} else {
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index d67144e..cbc9124 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -19,7 +19,6 @@
import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
-import android.os.storage.StorageManager;
import android.service.pm.PackageServiceDumpProto;
import android.util.ArraySet;
import android.util.proto.ProtoOutputStream;
@@ -167,10 +166,6 @@
return excludedUserIds == null ? EmptyArray.INT : excludedUserIds;
}
- public String getStorageSandboxName() {
- return StorageManager.SHARED_SANDBOX_PREFIX + name;
- }
-
/** Updates all fields in this shared user setting from another. */
public SharedUserSetting updateFrom(SharedUserSetting sharedUser) {
copyFrom(sharedUser);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 9782648..eec4b70 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -680,20 +680,23 @@
final List<ShortcutManager.ShareShortcutInfo> result = new ArrayList<>();
for (int i = 0; i < shortcuts.size(); i++) {
- final ShortcutInfo si = shortcuts.get(i);
+ final Set<String> categories = shortcuts.get(i).getCategories();
+ if (categories == null || categories.isEmpty()) {
+ continue;
+ }
for (int j = 0; j < matchedTargets.size(); j++) {
// Shortcut must have all of share target categories
boolean hasAllCategories = true;
final ShareTargetInfo target = matchedTargets.get(j);
for (int q = 0; q < target.mCategories.length; q++) {
- if (!si.getCategories().contains(target.mCategories[q])) {
+ if (!categories.contains(target.mCategories[q])) {
hasAllCategories = false;
break;
}
}
if (hasAllCategories) {
- result.add(new ShortcutManager.ShareShortcutInfo(si, new ComponentName(
- getPackageName(), target.mTargetClass)));
+ result.add(new ShortcutManager.ShareShortcutInfo(shortcuts.get(i),
+ new ComponentName(getPackageName(), target.mTargetClass)));
break;
}
}
@@ -706,6 +709,45 @@
}
/**
+ * Returns the number of shortcuts that can be used as a share target in the ShareSheet. Such
+ * shortcuts must have a matching category with at least one of the defined ShareTargets from
+ * the app's Xml resource.
+ */
+ int getSharingShortcutCount() {
+ if (mShortcuts.isEmpty() || mShareTargets.isEmpty()) {
+ return 0;
+ }
+
+ // Get the list of all dynamic shortcuts in this package
+ final ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+ findAll(shortcuts, ShortcutInfo::isDynamicVisible, ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
+
+ int sharingShortcutCount = 0;
+ for (int i = 0; i < shortcuts.size(); i++) {
+ final Set<String> categories = shortcuts.get(i).getCategories();
+ if (categories == null || categories.isEmpty()) {
+ continue;
+ }
+ for (int j = 0; j < mShareTargets.size(); j++) {
+ // A SharingShortcut must have all of share target categories
+ boolean hasAllCategories = true;
+ final ShareTargetInfo target = mShareTargets.get(j);
+ for (int q = 0; q < target.mCategories.length; q++) {
+ if (!categories.contains(target.mCategories[q])) {
+ hasAllCategories = false;
+ break;
+ }
+ }
+ if (hasAllCategories) {
+ sharingShortcutCount++;
+ break;
+ }
+ }
+ }
+ return sharingShortcutCount;
+ }
+
+ /**
* Return the filenames (excluding path names) of icon bitmap files from this package.
*/
public ArraySet<String> getUsedBitmapFiles() {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index daef4e0..2d8a2ac 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -95,6 +95,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -413,6 +414,9 @@
@GuardedBy("mLock")
private Exception mLastWtfStacktrace;
+ @GuardedBy("mLock")
+ private final MetricsLogger mMetricsLogger = new MetricsLogger();
+
static class InvalidFileFormatException extends Exception {
public InvalidFileFormatException(String message, Throwable cause) {
super(message, cause);
@@ -981,6 +985,8 @@
Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
file.failWrite(os);
}
+
+ getUserShortcutsLocked(userId).logSharingShortcutStats(mMetricsLogger);
}
@GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index 1fd9b69..8c207a8 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -20,6 +20,7 @@
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.pm.ShortcutManager;
+import android.metrics.LogMaker;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.ArrayMap;
@@ -27,6 +28,8 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.Preconditions;
import com.android.server.pm.ShortcutService.DumpFilter;
import com.android.server.pm.ShortcutService.InvalidFileFormatException;
@@ -647,4 +650,23 @@
return result;
}
+
+ void logSharingShortcutStats(MetricsLogger logger) {
+ int packageWithShareTargetsCount = 0;
+ int totalSharingShortcutCount = 0;
+ for (int i = 0; i < mPackages.size(); i++) {
+ if (mPackages.valueAt(i).hasShareTargets()) {
+ packageWithShareTargetsCount++;
+ totalSharingShortcutCount += mPackages.valueAt(i).getSharingShortcutCount();
+ }
+ }
+
+ final LogMaker logMaker = new LogMaker(MetricsEvent.ACTION_SHORTCUTS_CHANGED);
+ logger.write(logMaker.setType(MetricsEvent.SHORTCUTS_CHANGED_USER_ID)
+ .setSubtype(mUserId));
+ logger.write(logMaker.setType(MetricsEvent.SHORTCUTS_CHANGED_PACKAGE_COUNT)
+ .setSubtype(packageWithShareTargetsCount));
+ logger.write(logMaker.setType(MetricsEvent.SHORTCUTS_CHANGED_SHORTCUT_COUNT)
+ .setSubtype(totalSharingShortcutCount));
+ }
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 803ab2d..24bf18d 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -44,13 +44,11 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.storage.IStorageManager;
import android.util.Slog;
import android.util.SparseArray;
import android.util.apk.ApkSignatureVerifier;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.content.PackageHelper;
import com.android.internal.os.BackgroundThread;
import java.io.File;
@@ -115,7 +113,7 @@
return false;
}
- final PackageInfo packageInfo = mApexManager.getActivePackage(packageName);
+ final PackageInfo packageInfo = mApexManager.getPackageInfoForApexName(packageName);
if (packageInfo == null) {
// Only allow installing new apexes if on a debuggable build.
@@ -160,11 +158,28 @@
return false;
}
for (ApexInfo newPackage : apexInfoList.apexInfos) {
- PackageInfo activePackage = mApexManager.getActivePackage(newPackage.packageName);
+ PackageInfo activePackage = mApexManager.getPackageInfoForApexName(
+ newPackage.packageName);
if (activePackage == null) {
continue;
}
long activeVersion = activePackage.applicationInfo.longVersionCode;
+ if (session.params.requiredInstalledVersionCode
+ != PackageManager.VERSION_CODE_HIGHEST) {
+ if (activeVersion != session.params.requiredInstalledVersionCode) {
+ session.setStagedSessionFailed(
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "Installed version of APEX package " + newPackage.packageName
+ + " does not match required. Active version: " + activeVersion
+ + " required: " + session.params.requiredInstalledVersionCode);
+
+ if (!mApexManager.abortActiveSession()) {
+ Slog.e(TAG, "Failed to abort apex session " + session.sessionId);
+ }
+ return false;
+ }
+ }
+
boolean allowsDowngrade = PackageManagerServiceUtils.isDowngradePermitted(
session.params.installFlags, activePackage.applicationInfo.flags);
if (activeVersion > newPackage.versionCode && !allowsDowngrade) {
@@ -255,21 +270,6 @@
}
}
- // Make sure we start a filesystem checkpoint on the next boot.
- try {
- IStorageManager storageManager = PackageHelper.getStorageManager();
- if (storageManager.supportsCheckpoint()) {
- storageManager.startCheckpoint(1 /* numRetries */);
- }
- } catch (Exception e) { // TODO(b/130190815) make a RemoteException again
- // While StorageManager lives in the same process, the native implementation
- // it calls through lives in 'vold'; so, this call can fail if 'vold' isn't
- // reachable.
- // Since we can live without filesystem checkpointing, just warn in this case
- // and continue.
- Slog.w(TAG, "Could not start filesystem checkpoint:", e);
- }
-
session.setStagedSessionReady();
if (sessionContainsApex(session)
&& !mApexManager.markStagedSessionReady(session.sessionId)) {
@@ -384,6 +384,7 @@
PackageInstaller.SessionParams params = originalSession.params.copy();
params.isStaged = false;
params.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;
+ params.installFlags |= PackageManager.INSTALL_STAGED;
// TODO(b/129744602): use the userid from the original session.
int apkSessionId = mPi.createSession(
params, originalSession.getInstallerPackageName(),
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 108eaf6..8273752 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -744,12 +744,6 @@
TelephonyManager.ACTION_EMERGENCY_ASSISTANCE, userId),
userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
- // STOPSHIP(b/128289173): remove once EmergencyInfo app was replaced.
- grantSystemFixedPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(
- "com.android.emergency.action.EMERGENCY_ASSISTANCE", userId),
- userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
-
// NFC Tag viewer
Intent nfcTagIntent = new Intent(Intent.ACTION_VIEW)
.setType("vnd.android.cursor.item/ndef_msg");
@@ -855,21 +849,6 @@
grantPermissionsToSystemPackage(useOpenWifiPackage, userId, ALWAYS_LOCATION_PERMISSIONS);
}
- public void grantDefaultPermissionsToDefaultSmsApp(String packageName, int userId) {
- Log.i(TAG, "Granting permissions to default sms app for user:" + userId);
- grantIgnoringSystemPackage(packageName, userId,
- PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, SMS_PERMISSIONS, STORAGE_PERMISSIONS,
- MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
- }
-
- public void grantDefaultPermissionsToDefaultDialerApp(String packageName, int userId) {
- mServiceInternal.onDefaultDialerAppChanged(packageName, userId);
- Log.i(TAG, "Granting permissions to default dialer app for user:" + userId);
- grantIgnoringSystemPackage(packageName, userId,
- PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, SMS_PERMISSIONS,
- MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
- }
-
public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) {
Log.i(TAG, "Granting permissions to default Use Open WiFi app for user:" + userId);
grantIgnoringSystemPackage(packageName, userId, ALWAYS_LOCATION_PERMISSIONS);
@@ -1140,7 +1119,7 @@
private void grantRuntimePermissions(PackageInfo pkg, Set<String> permissionsWithoutSplits,
boolean systemFixed, boolean ignoreSystemPackage,
boolean whitelistRestrictedPermissions, int userId) {
- UserHandle user = UserHandle.of(userId);
+ UserHandle user = UserHandle.of(userId);
if (pkg == null) {
return;
}
@@ -1209,7 +1188,7 @@
if (ArrayUtils.isEmpty(disabledPkg.requestedPermissions)) {
return;
}
- if (!requestedPermissions.equals(disabledPkg.requestedPermissions)) {
+ if (!Arrays.equals(requestedPermissions, disabledPkg.requestedPermissions)) {
grantablePermissions = new ArraySet<>(Arrays.asList(requestedPermissions));
requestedPermissions = disabledPkg.requestedPermissions;
}
@@ -1219,7 +1198,7 @@
final int numRequestedPermissions = requestedPermissions.length;
// Sort requested permissions so that all permissions that are a foreground permission (i.e.
- // permisions that have background permission) are before their background permissions.
+ // permissions that have a background permission) are before their background permissions.
final String[] sortedRequestedPermissions = new String[numRequestedPermissions];
int numForeground = 0;
int numOther = 0;
@@ -1264,9 +1243,16 @@
continue;
}
- int uid = UserHandle.getUid(userId,
- UserHandle.getAppId(pkg.applicationInfo.uid));
- String op = AppOpsManager.permissionToOp(permission);
+ // Preserve whitelisting flags.
+ newFlags |= (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT);
+
+ // If we are whitelisting the permission, update the exempt flag before grant.
+ if (whitelistRestrictedPermissions && isPermissionRestricted(permission)) {
+ mContext.getPackageManager().updatePermissionFlags(permission,
+ pkg.packageName,
+ PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT,
+ PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, user);
+ }
if (pm.checkPermission(permission, pkg.packageName)
!= PackageManager.PERMISSION_GRANTED) {
@@ -1274,13 +1260,12 @@
.grantRuntimePermission(pkg.packageName, permission, user);
}
- if (whitelistRestrictedPermissions && isPermissionRestricted(permission)) {
- newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
- }
-
mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
newFlags, newFlags, user);
+ int uid = UserHandle.getUid(userId,
+ UserHandle.getAppId(pkg.applicationInfo.uid));
+
List<String> fgPerms = mPermissionManager.getBackgroundPermissions()
.get(permission);
if (fgPerms != null) {
@@ -1291,6 +1276,7 @@
if (pm.checkPermission(fgPerm, pkg.packageName)
== PackageManager.PERMISSION_GRANTED) {
// Upgrade the app-op state of the fg permission to allow bg access
+ // TODO: Dont' call app ops from package manager code.
mContext.getSystemService(AppOpsManager.class).setUidMode(
AppOpsManager.permissionToOp(fgPerm), uid,
AppOpsManager.MODE_ALLOWED);
@@ -1301,8 +1287,10 @@
}
String bgPerm = getBackgroundPermission(permission);
+ String op = AppOpsManager.permissionToOp(permission);
if (bgPerm == null) {
if (op != null) {
+ // TODO: Dont' call app ops from package manager code.
mContext.getSystemService(AppOpsManager.class).setUidMode(op, uid,
AppOpsManager.MODE_ALLOWED);
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index d45a8ef..b2ba290 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -32,7 +32,6 @@
import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM;
import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE;
import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS_ALL;
-import static android.content.pm.PackageManager.RESTRICTED_PERMISSIONS_ENABLED;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
@@ -930,6 +929,7 @@
final BasePermission bp = mSettings.getPermissionLocked(permName);
final boolean appSupportsRuntimePermissions =
pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M;
+ String upgradedActivityRecognitionPermission = null;
if (DEBUG_INSTALL) {
Log.i(TAG, "Package " + pkg.packageName + " checking " + permName + ": " + bp);
@@ -948,11 +948,40 @@
// Cache newImplicitPermissions before modifing permissionsState as for the shared
// uids the original and new state are the same object
if (!origPermissions.hasRequestedPermission(permName)
- && pkg.implicitPermissions.contains(permName)) {
- newImplicitPermissions.add(permName);
+ && (pkg.implicitPermissions.contains(permName)
+ || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) {
+ if (pkg.implicitPermissions.contains(permName)) {
+ // If permName is an implicit permission, try to auto-grant
+ newImplicitPermissions.add(permName);
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, permName + " is newly added for " + pkg.packageName);
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, permName + " is newly added for " + pkg.packageName);
+ }
+ } else {
+ // Special case for Activity Recognition permission. Even if AR permission
+ // is not an implicit permission we want to add it to the list (try to
+ // auto-grant it) if the app was installed on a device before AR permission
+ // was split, regardless of if the app now requests the new AR permission
+ // or has updated its target SDK and AR is no longer implicit to it.
+ // This is a compatibility workaround for apps when AR permission was
+ // split in Q.
+ int numSplitPerms = PermissionManager.SPLIT_PERMISSIONS.size();
+ for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
+ PermissionManager.SplitPermissionInfo sp =
+ PermissionManager.SPLIT_PERMISSIONS.get(splitPermNum);
+ String splitPermName = sp.getSplitPermission();
+ if (sp.getNewPermissions().contains(permName)
+ && origPermissions.hasInstallPermission(splitPermName)) {
+ upgradedActivityRecognitionPermission = splitPermName;
+ newImplicitPermissions.add(permName);
+
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, permName + " is newly added for "
+ + pkg.packageName);
+ }
+ break;
+ }
+ }
}
}
@@ -986,7 +1015,8 @@
// For all apps normal permissions are install time ones.
grant = GRANT_INSTALL;
} else if (bp.isRuntime()) {
- if (origPermissions.hasInstallPermission(bp.getName())) {
+ if (origPermissions.hasInstallPermission(bp.getName())
+ || upgradedActivityRecognitionPermission != null) {
// Before Q we represented some runtime permissions as install permissions,
// in Q we cannot do this anymore. Hence upgrade them all.
grant = GRANT_UPGRADE;
@@ -1058,8 +1088,8 @@
boolean wasChanged = false;
- boolean restrictionExempt = !RESTRICTED_PERMISSIONS_ENABLED
- || (origPermissions.getPermissionFlags(bp.name, userId)
+ boolean restrictionExempt =
+ (origPermissions.getPermissionFlags(bp.name, userId)
& FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
boolean restrictionApplied = (origPermissions.getPermissionFlags(
bp.name, userId) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
@@ -1162,10 +1192,15 @@
.getInstallPermissionState(perm);
int flags = (permState != null) ? permState.getFlags() : 0;
+ BasePermission bpToRevoke =
+ upgradedActivityRecognitionPermission == null
+ ? bp : mSettings.getPermissionLocked(
+ upgradedActivityRecognitionPermission);
// Remove install permission
- if (origPermissions.revokeInstallPermission(bp)
+ if (origPermissions.revokeInstallPermission(bpToRevoke)
!= PERMISSION_OPERATION_FAILURE) {
- origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
+ origPermissions.updatePermissionFlags(bpToRevoke,
+ UserHandle.USER_ALL,
(MASK_PERMISSION_FLAGS_ALL
& ~FLAG_PERMISSION_APPLY_RESTRICTION), 0);
changedInstallPermission = true;
@@ -1177,8 +1212,8 @@
for (int userId : currentUserIds) {
boolean wasChanged = false;
- boolean restrictionExempt = !RESTRICTED_PERMISSIONS_ENABLED
- || (origPermissions.getPermissionFlags(bp.name, userId)
+ boolean restrictionExempt =
+ (origPermissions.getPermissionFlags(bp.name, userId)
& FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
boolean restrictionApplied = (origPermissions.getPermissionFlags(
bp.name, userId) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
@@ -1490,9 +1525,11 @@
for (int userNum = 0; userNum < numUsers; userNum++) {
int userId = users[userNum];
- ps.updatePermissionFlags(bp, userId,
- FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
- FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
+ if (!newPerm.equals(Manifest.permission.ACTIVITY_RECOGNITION)) {
+ ps.updatePermissionFlags(bp, userId,
+ FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
+ FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
+ }
updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
boolean inheritsFromInstallPerm = false;
@@ -2054,7 +2091,7 @@
return;
}
- if (RESTRICTED_PERMISSIONS_ENABLED && bp.isHardOrSoftRestricted()
+ if (bp.isHardOrSoftRestricted()
&& (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
Log.e(TAG, "Cannot grant restricted non-exempt permission "
+ permName + " for package " + packageName);
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyInternal.java b/services/core/java/com/android/server/policy/PermissionPolicyInternal.java
new file mode 100644
index 0000000..ea8616c
--- /dev/null
+++ b/services/core/java/com/android/server/policy/PermissionPolicyInternal.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.policy;
+
+import android.annotation.NonNull;
+import android.content.Intent;
+
+/**
+ * Internal calls into {@link PermissionPolicyService}.
+ */
+public abstract class PermissionPolicyInternal {
+
+ /**
+ * Check whether an activity should be started.
+ *
+ * @param intent the {@link Intent} for the activity start
+ * @param callingUid the calling uid starting the activity
+ * @param callingPackage the calling package starting the activity
+ *
+ * @return whether the activity should be started
+ */
+ public abstract boolean checkStartActivity(@NonNull Intent intent, int callingUid,
+ @NonNull String callingPackage);
+}
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index a280d83..570a153 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -25,6 +25,8 @@
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -37,6 +39,8 @@
import android.os.UserHandle;
import android.permission.PermissionControllerManager;
import android.permission.PermissionManagerInternal;
+import android.provider.Telephony;
+import android.telecom.TelecomManager;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -59,6 +63,8 @@
public PermissionPolicyService(@NonNull Context context) {
super(context);
+
+ LocalServices.addService(PermissionPolicyInternal.class, new Internal());
}
@Override
@@ -104,7 +110,8 @@
// there as we are on the main thread and want to block until the work is
// completed or we time out.
final PermissionControllerManager permissionControllerManager =
- new PermissionControllerManager(context, FgThread.getHandler());
+ new PermissionControllerManager(getUserContext(context, UserHandle.of(userId)),
+ FgThread.getHandler());
permissionControllerManager.grantOrUpgradeDefaultRuntimePermissions(
FgThread.getExecutor(),
(Boolean success) -> {
@@ -326,8 +333,8 @@
return;
}
- final boolean applyRestriction = PackageManager.RESTRICTED_PERMISSIONS_ENABLED
- && (mPackageManager.getPermissionFlags(permission, pkg.packageName,
+ final boolean applyRestriction =
+ (mPackageManager.getPermissionFlags(permission, pkg.packageName,
mContext.getUser()) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
if (permissionInfo.isHardRestricted()) {
@@ -468,4 +475,47 @@
}
}
}
+
+ private class Internal extends PermissionPolicyInternal {
+
+ @Override
+ public boolean checkStartActivity(@NonNull Intent intent, int callingUid,
+ @NonNull String callingPackage) {
+ if (isActionRemovedForCallingPackage(intent.getAction(), callingPackage)) {
+ Slog.w(LOG_TAG, "Action Removed: starting " + intent.toString() + " from "
+ + callingPackage + " (uid=" + callingUid + ")");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check if the intent action is removed for the calling package (often based on target SDK
+ * version). If the action is removed, we'll silently cancel the activity launch.
+ */
+ private boolean isActionRemovedForCallingPackage(@Nullable String action,
+ @NonNull String callingPackage) {
+ if (action == null) {
+ return false;
+ }
+ switch (action) {
+ case TelecomManager.ACTION_CHANGE_DEFAULT_DIALER:
+ case Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT: {
+ ApplicationInfo applicationInfo;
+ try {
+ applicationInfo = getContext().getPackageManager().getApplicationInfo(
+ callingPackage, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.i(LOG_TAG, "Cannot find application info for " + callingPackage);
+ return false;
+ }
+ // Applications targeting Q should use RoleManager.createRequestRoleIntent()
+ // instead.
+ return applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
+ }
+ default:
+ return false;
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index a65a812..14f1196 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -75,6 +75,8 @@
*/
private final AtomicBoolean mRequested;
+ private long mLastActedOnNextScreenDimming;
+
/**
* Monotonously increasing ID for the requests sent.
*/
@@ -150,6 +152,9 @@
}
public long updateUserActivity(long nextScreenDimming) {
+ if (nextScreenDimming == mLastActedOnNextScreenDimming) {
+ return nextScreenDimming;
+ }
if (!mIsSettingEnabled) {
return nextScreenDimming;
}
@@ -190,13 +195,14 @@
// afterwards if AttentionManager couldn't deliver it.
mRequested.set(true);
mRequestId++;
+ mLastActedOnNextScreenDimming = nextScreenDimming;
mCallback = new AttentionCallbackInternalImpl(mRequestId);
+ Slog.v(TAG, "Checking user attention, ID: " + mRequestId);
final boolean sent = mAttentionManager.checkAttention(getAttentionTimeout(), mCallback);
if (!sent) {
mRequested.set(false);
}
- Slog.v(TAG, "Checking user attention");
return whenToCheck;
}
@@ -277,12 +283,12 @@
}
public void dump(PrintWriter pw) {
- pw.print("AttentionDetector:");
- pw.print(" mMaximumExtensionMillis=" + mMaximumExtensionMillis);
- pw.print(" mMaxAttentionApiTimeoutMillis=" + mMaxAttentionApiTimeoutMillis);
- pw.print(" mLastUserActivityTime(excludingAttention)=" + mLastUserActivityTime);
- pw.print(" mAttentionServiceSupported=" + isAttentionServiceSupported());
- pw.print(" mRequested=" + mRequested);
+ pw.println("AttentionDetector:");
+ pw.println(" mMaximumExtensionMillis=" + mMaximumExtensionMillis);
+ pw.println(" mMaxAttentionApiTimeoutMillis=" + mMaxAttentionApiTimeoutMillis);
+ pw.println(" mLastUserActivityTime(excludingAttention)=" + mLastUserActivityTime);
+ pw.println(" mAttentionServiceSupported=" + isAttentionServiceSupported());
+ pw.println(" mRequested=" + mRequested);
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 0e20905..33803b7 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -156,6 +156,7 @@
PackageManagerInternal packageManagerInternal = LocalServices.getService(
PackageManagerInternal.class);
packageManagerInternal.setDefaultBrowserProvider(new DefaultBrowserProvider());
+ packageManagerInternal.setDefaultDialerProvider(new DefaultDialerProvider());
packageManagerInternal.setDefaultHomeProvider(new DefaultHomeProvider());
registerUserRemovedReceiver();
@@ -772,6 +773,16 @@
}
}
+ private class DefaultDialerProvider implements PackageManagerInternal.DefaultDialerProvider {
+
+ @Nullable
+ @Override
+ public String getDefaultDialer(@UserIdInt int userId) {
+ return CollectionUtils.firstOrNull(getOrCreateUserState(userId).getRoleHolders(
+ RoleManager.ROLE_DIALER));
+ }
+ }
+
private class DefaultHomeProvider implements PackageManagerInternal.DefaultHomeProvider {
@Nullable
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index db2c742..944e4b8 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -50,6 +50,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.DeviceConfig;
+import android.util.ArraySet;
import android.util.IntArray;
import android.util.Log;
import android.util.SparseBooleanArray;
@@ -59,6 +60,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
+import com.android.server.Watchdog;
import com.android.server.pm.Installer;
import java.io.File;
@@ -69,11 +71,9 @@
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
@@ -100,6 +100,9 @@
// handler threads are running so that's fine.
private long mRollbackLifetimeDurationInMillis = DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS;
+ private static final long HANDLER_THREAD_TIMEOUT_DURATION_MILLIS =
+ TimeUnit.MINUTES.toMillis(10);
+
// Used for generating rollback IDs.
private final Random mRandom = new SecureRandom();
@@ -107,15 +110,9 @@
@GuardedBy("mLock")
private final SparseBooleanArray mAllocatedRollbackIds = new SparseBooleanArray();
- // Package rollback data for rollback-enabled installs that have not yet
- // been committed. Maps from sessionId to rollback data.
+ // Package rollback data for rollbacks we are in the process of enabling.
@GuardedBy("mLock")
- private final Map<Integer, RollbackData> mPendingRollbacks = new HashMap<>();
-
- // Map from child session id's for enabled rollbacks to their
- // corresponding parent session ids.
- @GuardedBy("mLock")
- private final Map<Integer, Integer> mChildSessions = new HashMap<>();
+ private final Set<NewRollback> mNewRollbacks = new ArraySet<>();
// The list of all rollbacks, including available and committed rollbacks.
// This list is null until the rollback data has been loaded.
@@ -136,7 +133,6 @@
// No need for guarding with lock because value is only accessed in handler thread.
private long mRelativeBootTime = calculateRelativeBootTime();
-
RollbackManagerServiceImpl(Context context) {
mContext = context;
// Note that we're calling onStart here because this object is only constructed on
@@ -146,6 +142,9 @@
mHandlerThread = new HandlerThread("RollbackManagerServiceHandler");
mHandlerThread.start();
+ // Monitor the handler thread
+ Watchdog.getInstance().addThread(getHandler(), HANDLER_THREAD_TIMEOUT_DURATION_MILLIS);
+
mRollbackStore = new RollbackStore(new File(Environment.getDataDirectory(), "rollback"));
mPackageHealthObserver = new RollbackPackageHealthObserver(mContext);
@@ -192,7 +191,7 @@
getHandler().post(() -> {
boolean success = enableRollback(installFlags, newPackageCodePath,
- installedUsers, user);
+ installedUsers, user, token);
int ret = PackageManagerInternal.ENABLE_ROLLBACK_SUCCEEDED;
if (!success) {
ret = PackageManagerInternal.ENABLE_ROLLBACK_FAILED;
@@ -211,6 +210,27 @@
}
}, enableRollbackFilter, null, getHandler());
+ IntentFilter enableRollbackTimedOutFilter = new IntentFilter();
+ enableRollbackTimedOutFilter.addAction(Intent.ACTION_CANCEL_ENABLE_ROLLBACK);
+
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_CANCEL_ENABLE_ROLLBACK.equals(intent.getAction())) {
+ int token = intent.getIntExtra(
+ PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, -1);
+ synchronized (mLock) {
+ for (NewRollback rollback : mNewRollbacks) {
+ if (rollback.hasToken(token)) {
+ rollback.isCancelled = true;
+ return;
+ }
+ }
+ }
+ }
+ }
+ }, enableRollbackTimedOutFilter, null, getHandler());
+
registerTimeChangeReceiver();
}
@@ -247,9 +267,20 @@
}, filter, null, getHandler());
}
+ /**
+ * This method posts a blocking call to the handler thread, so it should not be called from
+ * that same thread.
+ * @throws {@link IllegalStateException} if called from {@link #mHandlerThread}
+ */
@Override
public ParceledListSlice getAvailableRollbacks() {
enforceManageRollbacks("getAvailableRollbacks");
+ if (Thread.currentThread().equals(mHandlerThread)) {
+ Log.wtf(TAG, "Calling getAvailableRollbacks from mHandlerThread "
+ + "causes a deadlock");
+ throw new IllegalStateException("Cannot call RollbackManager#getAvailableRollbacks "
+ + "from the handler thread!");
+ }
// Wait for the handler thread to get the list of available rollbacks
// to get the most up-to-date results. This is intended to reduce test
@@ -357,31 +388,6 @@
return;
}
- // Verify the RollbackData is up to date with what's installed on
- // device.
- // TODO: We assume that between now and the time we commit the
- // downgrade install, the currently installed package version does not
- // change. This is not safe to assume, particularly in the case of a
- // rollback racing with a roll-forward fix of a buggy package.
- // Figure out how to ensure we don't commit the rollback if
- // roll forward happens at the same time.
- for (PackageRollbackInfo info : data.info.getPackages()) {
- VersionedPackage installedVersion = getInstalledPackageVersion(info.getPackageName());
- if (installedVersion == null) {
- // TODO: Test this case
- sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE,
- "Package to roll back is not installed");
- return;
- }
-
- if (!packageVersionsEqual(info.getVersionRolledBackFrom(), installedVersion)) {
- // TODO: Test this case
- sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE,
- "Package version to roll back not installed.");
- return;
- }
- }
-
// Get a context for the caller to use to install the downgraded
// version of the package.
Context context = null;
@@ -420,6 +426,8 @@
}
}
params.setRequestDowngrade(true);
+ params.setRequiredInstalledVersionCode(
+ info.getVersionRolledBackFrom().getLongVersionCode());
if (data.isStaged()) {
params.setStaged();
}
@@ -649,8 +657,7 @@
// hasn't actually been updated.
onPackageReplaced(apexPackageName);
}
-
- mPackageHealthObserver.onBootCompleted();
+ mPackageHealthObserver.onBootCompletedAsync();
});
}
@@ -839,16 +846,16 @@
* @param newPackageCodePath path to the package about to be installed.
* @param installedUsers the set of users for which a given package is installed.
* @param user the user that owns the install session to enable rollback on.
+ * @param token the distinct rollback token sent by package manager.
* @return true if enabling the rollback succeeds, false otherwise.
*/
private boolean enableRollback(int installFlags, File newPackageCodePath,
- int[] installedUsers, @UserIdInt int user) {
+ int[] installedUsers, @UserIdInt int user, int token) {
// Find the session id associated with this install.
// TODO: It would be nice if package manager or package installer told
// us the session directly, rather than have to search for it
// ourselves.
- PackageInstaller.SessionInfo session = null;
// getAllSessions only returns sessions for the associated user.
// Create a context with the right user so we can find the matching
@@ -859,7 +866,8 @@
return false;
}
- int parentSessionId = -1;
+ PackageInstaller.SessionInfo parentSession = null;
+ PackageInstaller.SessionInfo packageSession = null;
PackageInstaller installer = context.getPackageManager().getPackageInstaller();
for (PackageInstaller.SessionInfo info : installer.getAllSessions()) {
if (info.isMultiPackage()) {
@@ -867,21 +875,21 @@
PackageInstaller.SessionInfo child = installer.getSessionInfo(childId);
if (sessionMatchesForEnableRollback(child, installFlags, newPackageCodePath)) {
// TODO: Check we only have one matching session?
- parentSessionId = info.getSessionId();
- session = child;
+ parentSession = info;
+ packageSession = child;
break;
}
}
} else if (sessionMatchesForEnableRollback(info, installFlags, newPackageCodePath)) {
// TODO: Check we only have one matching session?
- parentSessionId = info.getSessionId();
- session = info;
+ parentSession = info;
+ packageSession = info;
break;
}
}
- if (session == null) {
- Log.e(TAG, "Unable to find session id for enabled rollback.");
+ if (parentSession == null || packageSession == null) {
+ Log.e(TAG, "Unable to find session for enabled rollback.");
return false;
}
@@ -893,7 +901,7 @@
ensureRollbackDataLoadedLocked();
for (int i = 0; i < mRollbacks.size(); ++i) {
RollbackData data = mRollbacks.get(i);
- if (data.apkSessionId == parentSessionId) {
+ if (data.apkSessionId == parentSession.getSessionId()) {
rd = data;
break;
}
@@ -906,7 +914,7 @@
PackageParser.PackageLite newPackage = null;
try {
newPackage = PackageParser.parsePackageLite(
- new File(session.resolvedBaseCodePath), 0);
+ new File(packageSession.resolvedBaseCodePath), 0);
} catch (PackageParser.PackageParserException e) {
Log.e(TAG, "Unable to parse new package", e);
return false;
@@ -924,16 +932,33 @@
return false;
}
- return enableRollbackForSession(session, installedUsers, true);
+ NewRollback newRollback;
+ synchronized (mLock) {
+ // See if we already have a NewRollback that contains this package
+ // session. If not, create a NewRollback for the parent session
+ // that we will use for all the packages in the session.
+ newRollback = getNewRollbackForPackageSessionLocked(packageSession.getSessionId());
+ if (newRollback == null) {
+ newRollback = createNewRollbackLocked(parentSession);
+ mNewRollbacks.add(newRollback);
+ }
+ }
+ newRollback.addToken(token);
+
+ return enableRollbackForPackageSession(newRollback.data, packageSession,
+ installedUsers, /* snapshotUserData*/ true);
}
/**
* Do code and userdata backups to enable rollback of the given session.
* In case of multiPackage sessions, <code>session</code> should be one of
* the child sessions, not the parent session.
+ *
+ * @return true on success, false on failure.
*/
- private boolean enableRollbackForSession(PackageInstaller.SessionInfo session,
- @NonNull int[] installedUsers, boolean snapshotUserData) {
+ private boolean enableRollbackForPackageSession(RollbackData data,
+ PackageInstaller.SessionInfo session, @NonNull int[] installedUsers,
+ boolean snapshotUserData) {
// TODO: Don't attempt to enable rollback for split installs.
final int installFlags = session.installFlags;
if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
@@ -988,41 +1013,14 @@
VersionedPackage installedVersion = new VersionedPackage(packageName,
pkgInfo.getLongVersionCode());
- PackageRollbackInfo info = new PackageRollbackInfo(newVersion, installedVersion,
+ PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(
+ newVersion, installedVersion,
new IntArray() /* pendingBackups */, new ArrayList<>() /* pendingRestores */,
isApex, IntArray.wrap(installedUsers),
new SparseLongArray() /* ceSnapshotInodes */);
- RollbackData data;
- try {
- int childSessionId = session.getSessionId();
- int parentSessionId = session.getParentSessionId();
- if (parentSessionId == PackageInstaller.SessionInfo.INVALID_ID) {
- parentSessionId = childSessionId;
- }
-
- synchronized (mLock) {
- // TODO: no need to add to mChildSessions if childSessionId is
- // the same as parentSessionId.
- mChildSessions.put(childSessionId, parentSessionId);
- data = mPendingRollbacks.get(parentSessionId);
- if (data == null) {
- int rollbackId = allocateRollbackIdLocked();
- if (session.isStaged()) {
- data = mRollbackStore.createStagedRollback(rollbackId, parentSessionId);
- } else {
- data = mRollbackStore.createNonStagedRollback(rollbackId);
- }
- mPendingRollbacks.put(parentSessionId, data);
- }
- data.info.getPackages().add(info);
- }
- } catch (IOException e) {
- Log.e(TAG, "Unable to create rollback for " + packageName, e);
- return false;
- }
if (snapshotUserData && !isApex) {
- mAppDataRollbackHelper.snapshotAppData(data.info.getRollbackId(), info);
+ mAppDataRollbackHelper.snapshotAppData(data.info.getRollbackId(), packageRollbackInfo);
}
try {
@@ -1037,6 +1035,10 @@
Log.e(TAG, "Unable to copy package for rollback for " + packageName, e);
return false;
}
+
+ synchronized (mLock) {
+ data.info.getPackages().add(packageRollbackInfo);
+ }
return true;
}
@@ -1044,7 +1046,7 @@
public void restoreUserData(String packageName, int[] userIds, int appId, long ceDataInode,
String seInfo, int token) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException("restoureUserData may only be called by the system.");
+ throw new SecurityException("restoreUserData may only be called by the system.");
}
getHandler().post(() -> {
@@ -1107,8 +1109,14 @@
return;
}
+ NewRollback newRollback;
+ synchronized (mLock) {
+ newRollback = createNewRollbackLocked(session);
+ }
+
if (!session.isMultiPackage()) {
- if (!enableRollbackForSession(session, new int[0], false)) {
+ if (!enableRollbackForPackageSession(newRollback.data, session,
+ new int[0], /* snapshotUserData */ false)) {
Log.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false);
return;
@@ -1122,7 +1130,8 @@
result.offer(false);
return;
}
- if (!enableRollbackForSession(childSession, new int[0], false)) {
+ if (!enableRollbackForPackageSession(newRollback.data, childSession,
+ new int[0], /* snapshotUserData */ false)) {
Log.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false);
return;
@@ -1130,8 +1139,7 @@
}
}
- completeEnableRollback(sessionId, true);
- result.offer(true);
+ result.offer(completeEnableRollback(newRollback, true) != null);
});
try {
@@ -1262,9 +1270,19 @@
@Override
public void onFinished(int sessionId, boolean success) {
- RollbackData rollback = completeEnableRollback(sessionId, success);
- if (rollback != null && !rollback.isStaged()) {
- makeRollbackAvailable(rollback);
+ NewRollback newRollback;
+ synchronized (mLock) {
+ newRollback = getNewRollbackForPackageSessionLocked(sessionId);
+ if (newRollback != null) {
+ mNewRollbacks.remove(newRollback);
+ }
+ }
+
+ if (newRollback != null) {
+ RollbackData rollback = completeEnableRollback(newRollback, success);
+ if (rollback != null && !rollback.isStaged()) {
+ makeRollbackAvailable(rollback);
+ }
}
}
}
@@ -1274,25 +1292,27 @@
* This should be called after rollback has been enabled for all packages
* in the rollback. It does not make the rollback available yet.
*
- * @return the rollback data for a successfully enable-completed rollback.
+ * @return the rollback data for a successfully enable-completed rollback,
+ * or null on error.
*/
- private RollbackData completeEnableRollback(int sessionId, boolean success) {
- RollbackData data = null;
- synchronized (mLock) {
- Integer parentSessionId = mChildSessions.remove(sessionId);
- if (parentSessionId != null) {
- sessionId = parentSessionId;
- }
-
- data = mPendingRollbacks.remove(sessionId);
+ private RollbackData completeEnableRollback(NewRollback newRollback, boolean success) {
+ RollbackData data = newRollback.data;
+ if (!success) {
+ // The install session was aborted, clean up the pending install.
+ deleteRollback(data);
+ return null;
}
-
- if (data == null) {
+ if (newRollback.isCancelled) {
+ Log.e(TAG, "Rollback has been cancelled by PackageManager");
+ deleteRollback(data);
return null;
}
- if (!success) {
- // The install session was aborted, clean up the pending install.
+ // It's safe to access data.info outside a synchronized block because
+ // this is running on the handler thread and all changes to the
+ // data.info occur on the handler thread.
+ if (data.info.getPackages().size() != newRollback.packageSessionIds.length) {
+ Log.e(TAG, "Failed to enable rollback for all packages in session.");
deleteRollback(data);
return null;
}
@@ -1376,7 +1396,7 @@
}
@GuardedBy("mLock")
- private int allocateRollbackIdLocked() throws IOException {
+ private int allocateRollbackIdLocked() {
int n = 0;
int rollbackId;
do {
@@ -1387,7 +1407,7 @@
}
} while (n++ < 32);
- throw new IOException("Failed to allocate rollback ID");
+ throw new IllegalStateException("Failed to allocate rollback ID");
}
private void deleteRollback(RollbackData rollbackData) {
@@ -1462,4 +1482,88 @@
+ Manifest.permission.TEST_MANAGE_ROLLBACKS);
}
}
+
+ private static class NewRollback {
+ public final RollbackData data;
+
+ /**
+ * This array holds all of the rollback tokens associated with package sessions included
+ * in this rollback. This is used to identify which rollback should be cancelled in case
+ * {@link PackageManager} sends an {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK} intent.
+ */
+ private final IntArray mTokens = new IntArray();
+
+ /**
+ * Session ids for all packages in the install.
+ * For multi-package sessions, this is the list of child session ids.
+ * For normal sessions, this list is a single element with the normal
+ * session id.
+ */
+ public final int[] packageSessionIds;
+
+ /**
+ * Flag to determine whether the RollbackData has been cancelled.
+ *
+ * <p>RollbackData could be invalidated and cancelled if RollbackManager receives
+ * {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK} from {@link PackageManager}.
+ *
+ * <p>The main underlying assumption here is that if enabling the rollback times out, then
+ * {@link PackageManager} will NOT send
+ * {@link PackageInstaller.SessionCallback#onFinished(int, boolean)} before it broadcasts
+ * {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK}.
+ */
+ public boolean isCancelled = false;
+
+ NewRollback(RollbackData data, int[] packageSessionIds) {
+ this.data = data;
+ this.packageSessionIds = packageSessionIds;
+ }
+
+ public void addToken(int token) {
+ mTokens.add(token);
+ }
+
+ public boolean hasToken(int token) {
+ return mTokens.indexOf(token) != -1;
+ }
+ }
+
+ NewRollback createNewRollbackLocked(PackageInstaller.SessionInfo parentSession) {
+ int rollbackId = allocateRollbackIdLocked();
+ final RollbackData data;
+ int parentSessionId = parentSession.getSessionId();
+
+ if (parentSession.isStaged()) {
+ data = mRollbackStore.createStagedRollback(rollbackId, parentSessionId);
+ } else {
+ data = mRollbackStore.createNonStagedRollback(rollbackId);
+ }
+
+ int[] packageSessionIds;
+ if (parentSession.isMultiPackage()) {
+ packageSessionIds = parentSession.getChildSessionIds();
+ } else {
+ packageSessionIds = new int[]{parentSessionId};
+ }
+
+ return new NewRollback(data, packageSessionIds);
+ }
+
+ /**
+ * Returns the NewRollback associated with the given package session.
+ * Returns null if no NewRollback is found for the given package
+ * session.
+ */
+ NewRollback getNewRollbackForPackageSessionLocked(int packageSessionId) {
+ // We expect mNewRollbacks to be a very small list; linear search
+ // should be plenty fast.
+ for (NewRollback newRollbackData : mNewRollbacks) {
+ for (int id : newRollbackData.packageSessionIds) {
+ if (id == packageSessionId) {
+ return newRollbackData;
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 748a661..bcef66c 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -32,6 +32,7 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.PowerManager;
+import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Slog;
import android.util.StatsLog;
@@ -49,9 +50,12 @@
import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.TimeUnit;
/**
- * {@code PackageHealthObserver} for {@code RollbackManagerService}.
+ * {@link PackageHealthObserver} for {@link RollbackManagerService}.
+ * This class monitors crashes and triggers RollbackManager rollback accordingly.
+ * It also monitors native crashes for some short while after boot.
*
* @hide
*/
@@ -59,12 +63,21 @@
private static final String TAG = "RollbackPackageHealthObserver";
private static final String NAME = "rollback-observer";
private static final int INVALID_ROLLBACK_ID = -1;
+ // TODO: make the following values configurable via DeviceConfig
+ private static final long NATIVE_CRASH_POLLING_INTERVAL_MILLIS =
+ TimeUnit.SECONDS.toMillis(30);
+ private static final long NUMBER_OF_NATIVE_CRASH_POLLS = 10;
+
private final Context mContext;
private final Handler mHandler;
private final File mLastStagedRollbackIdFile;
+ // this field is initialized in the c'tor and then only accessed from mHandler thread, so
+ // no need to guard with a lock
+ private long mNumberOfNativeCrashPollsRemaining;
RollbackPackageHealthObserver(Context context) {
mContext = context;
+ mNumberOfNativeCrashPollsRemaining = NUMBER_OF_NATIVE_CRASH_POLLS;
HandlerThread handlerThread = new HandlerThread("RollbackPackageHealthObserver");
handlerThread.start();
mHandler = handlerThread.getThreadHandler();
@@ -76,8 +89,6 @@
@Override
public int onHealthCheckFailed(VersionedPackage failedPackage) {
- VersionedPackage moduleMetadataPackage = getModuleMetadataPackage();
-
if (getAvailableRollback(mContext.getSystemService(RollbackManager.class), failedPackage)
== null) {
// Don't handle the notification, no rollbacks available for the package
@@ -145,16 +156,29 @@
PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs);
}
- /** Verifies the rollback state after a reboot. */
- public void onBootCompleted() {
+ /** Verifies the rollback state after a reboot and schedules polling for sometime after reboot
+ * to check for native crashes and mitigate them if needed.
+ */
+ public void onBootCompletedAsync() {
+ mHandler.post(()->onBootCompleted());
+ }
+
+ private void onBootCompleted() {
+ RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
+ PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
+ String moduleMetadataPackageName = getModuleMetadataPackageName();
+ VersionedPackage newModuleMetadataPackage = getModuleMetadataPackage();
+
+ if (getAvailableRollback(rollbackManager, newModuleMetadataPackage) != null) {
+ scheduleCheckAndMitigateNativeCrashes();
+ }
+
int rollbackId = popLastStagedRollbackId();
if (rollbackId == INVALID_ROLLBACK_ID) {
// No staged rollback before reboot
return;
}
- RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
- PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
RollbackInfo rollback = null;
for (RollbackInfo info : rollbackManager.getRecentlyCommittedRollbacks()) {
if (rollbackId == info.getRollbackId()) {
@@ -168,14 +192,12 @@
return;
}
- String moduleMetadataPackageName = getModuleMetadataPackageName();
-
// Use the version of the metadata package that was installed before
// we rolled back for logging purposes.
- VersionedPackage moduleMetadataPackage = null;
+ VersionedPackage oldModuleMetadataPackage = null;
for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
if (packageRollback.getPackageName().equals(moduleMetadataPackageName)) {
- moduleMetadataPackage = packageRollback.getVersionRolledBackFrom();
+ oldModuleMetadataPackage = packageRollback.getVersionRolledBackFrom();
break;
}
}
@@ -187,12 +209,12 @@
return;
}
if (sessionInfo.isStagedSessionApplied()) {
- logEvent(moduleMetadataPackage,
+ logEvent(oldModuleMetadataPackage,
StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS);
} else if (sessionInfo.isStagedSessionReady()) {
// TODO: What do for staged session ready but not applied
} else {
- logEvent(moduleMetadataPackage,
+ logEvent(oldModuleMetadataPackage,
StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE);
}
}
@@ -320,4 +342,34 @@
moduleMetadataPackage.getPackageName(), moduleMetadataPackage.getVersionCode());
}
}
+
+ /**
+ * This method should be only called on mHandler thread, since it modifies
+ * {@link #mNumberOfNativeCrashPollsRemaining} and we want to keep this class lock free.
+ */
+ private void checkAndMitigateNativeCrashes() {
+ mNumberOfNativeCrashPollsRemaining--;
+ // Check if native watchdog reported a crash
+ if ("1".equals(SystemProperties.get("ro.init.updatable_crashing"))) {
+ execute(getModuleMetadataPackage());
+ // we stop polling after an attempt to execute rollback, regardless of whether the
+ // attempt succeeds or not
+ } else {
+ if (mNumberOfNativeCrashPollsRemaining > 0) {
+ mHandler.postDelayed(() -> checkAndMitigateNativeCrashes(),
+ NATIVE_CRASH_POLLING_INTERVAL_MILLIS);
+ }
+ }
+ }
+
+ /**
+ * Since this method can eventually trigger a RollbackManager rollback, it should be called
+ * only once boot has completed {@code onBootCompleted} and not earlier, because the install
+ * session must be entirely completed before we try to rollback.
+ */
+ private void scheduleCheckAndMitigateNativeCrashes() {
+ Slog.i(TAG, "Scheduling " + mNumberOfNativeCrashPollsRemaining + " polls to check "
+ + "and mitigate native crashes");
+ mHandler.post(()->checkAndMitigateNativeCrashes());
+ }
}
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 2cfa465..8a26368c 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -194,7 +194,7 @@
* Creates a new RollbackData instance for a non-staged rollback with
* backupDir assigned.
*/
- RollbackData createNonStagedRollback(int rollbackId) throws IOException {
+ RollbackData createNonStagedRollback(int rollbackId) {
File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
return new RollbackData(rollbackId, backupDir, -1);
}
@@ -203,8 +203,7 @@
* Creates a new RollbackData instance for a staged rollback with
* backupDir assigned.
*/
- RollbackData createStagedRollback(int rollbackId, int stagedSessionId)
- throws IOException {
+ RollbackData createStagedRollback(int rollbackId, int stagedSessionId) {
File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
return new RollbackData(rollbackId, backupDir, stagedSessionId);
}
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index f581bc0..e65eae0 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -70,38 +70,9 @@
ServiceManager.addService(Context.TELECOM_SERVICE, service);
synchronized (mLock) {
- if (mDefaultSmsAppRequests != null || mDefaultDialerAppRequests != null
- || mDefaultSimCallManagerRequests != null) {
+ if (mDefaultSimCallManagerRequests != null) {
final DefaultPermissionGrantPolicy permissionPolicy =
getDefaultPermissionGrantPolicy();
-
- if (mDefaultSmsAppRequests != null) {
- ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
- mContext, true);
- if (smsComponent != null) {
- final int requestCount = mDefaultSmsAppRequests.size();
- for (int i = requestCount - 1; i >= 0; i--) {
- final int userid = mDefaultSmsAppRequests.get(i);
- mDefaultSmsAppRequests.remove(i);
- permissionPolicy.grantDefaultPermissionsToDefaultSmsApp(
- smsComponent.getPackageName(), userid);
- }
- }
- }
-
- if (mDefaultDialerAppRequests != null) {
- String packageName = DefaultDialerManager.getDefaultDialerApplication(
- mContext);
- if (packageName != null) {
- final int requestCount = mDefaultDialerAppRequests.size();
- for (int i = requestCount - 1; i >= 0; i--) {
- final int userId = mDefaultDialerAppRequests.get(i);
- mDefaultDialerAppRequests.remove(i);
- permissionPolicy.grantDefaultPermissionsToDefaultDialerApp(
- packageName, userId);
- }
- }
- }
if (mDefaultSimCallManagerRequests != null) {
TelecomManager telecomManager =
(TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
@@ -146,12 +117,6 @@
private final Object mLock = new Object();
@GuardedBy("mLock")
- private IntArray mDefaultSmsAppRequests;
-
- @GuardedBy("mLock")
- private IntArray mDefaultDialerAppRequests;
-
- @GuardedBy("mLock")
private IntArray mDefaultSimCallManagerRequests;
private final Context mContext;
@@ -207,10 +172,6 @@
permissionPolicy.setSmsAppPackagesProvider(userId -> {
synchronized (mLock) {
if (mServiceConnection == null) {
- if (mDefaultSmsAppRequests == null) {
- mDefaultSmsAppRequests = new IntArray();
- }
- mDefaultSmsAppRequests.add(userId);
return null;
}
}
@@ -226,10 +187,6 @@
permissionPolicy.setDialerAppPackagesProvider(userId -> {
synchronized (mLock) {
if (mServiceConnection == null) {
- if (mDefaultDialerAppRequests == null) {
- mDefaultDialerAppRequests = new IntArray();
- }
- mDefaultDialerAppRequests.add(userId);
return null;
}
}
@@ -263,38 +220,18 @@
private void registerDefaultAppNotifier() {
final DefaultPermissionGrantPolicy permissionPolicy = getDefaultPermissionGrantPolicy();
-
// Notify the package manager on default app changes
- final Uri defaultSmsAppUri = Settings.Secure.getUriFor(
- Settings.Secure.SMS_DEFAULT_APPLICATION);
final Uri defaultDialerAppUri = Settings.Secure.getUriFor(
Settings.Secure.DIALER_DEFAULT_APPLICATION);
-
ContentObserver contentObserver = new ContentObserver(
new Handler(Looper.getMainLooper())) {
@Override
public void onChange(boolean selfChange, Uri uri, int userId) {
- if (defaultSmsAppUri.equals(uri)) {
- ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
- mContext, true);
- if (smsComponent != null) {
- permissionPolicy.grantDefaultPermissionsToDefaultSmsApp(
- smsComponent.getPackageName(), userId);
- }
- } else if (defaultDialerAppUri.equals(uri)) {
- String packageName = DefaultDialerManager.getDefaultDialerApplication(
- mContext);
- if (packageName != null) {
- permissionPolicy.grantDefaultPermissionsToDefaultDialerApp(
- packageName, userId);
- }
+ if (defaultDialerAppUri.equals(uri)) {
updateSimCallManagerPermissions(permissionPolicy, userId);
}
}
};
-
- mContext.getContentResolver().registerContentObserver(defaultSmsAppUri,
- false, contentObserver, UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(defaultDialerAppUri,
false, contentObserver, UserHandle.USER_ALL);
}
diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
index 0b0ff66..fcf87ee 100644
--- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java
+++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
@@ -105,9 +105,8 @@
*/
private void setUpTestHarnessMode() {
Slog.d(TAG, "Setting up test harness mode");
- byte[] testHarnessModeData = getPersistentDataBlock().getTestHarnessModeData();
- if (testHarnessModeData == null || testHarnessModeData.length == 0) {
- // There's no data to apply, so leave it as-is.
+ byte[] testHarnessModeData = getTestHarnessModeData();
+ if (testHarnessModeData == null) {
return;
}
// If there is data, we should set the device as provisioned, so that we skip the setup
@@ -125,9 +124,8 @@
private void completeTestHarnessModeSetup() {
Slog.d(TAG, "Completing Test Harness Mode setup.");
- byte[] testHarnessModeData = getPersistentDataBlock().getTestHarnessModeData();
- if (testHarnessModeData == null || testHarnessModeData.length == 0) {
- // There's no data to apply, so leave it as-is.
+ byte[] testHarnessModeData = getTestHarnessModeData();
+ if (testHarnessModeData == null) {
return;
}
try {
@@ -145,6 +143,21 @@
}
}
+ private byte[] getTestHarnessModeData() {
+ PersistentDataBlockManagerInternal blockManager = getPersistentDataBlock();
+ if (blockManager == null) {
+ Slog.e(TAG, "Failed to start Test Harness Mode; no implementation of "
+ + "PersistentDataBlockManagerInternal was bound!");
+ return null;
+ }
+ byte[] testHarnessModeData = blockManager.getTestHarnessModeData();
+ if (testHarnessModeData == null || testHarnessModeData.length == 0) {
+ // There's no data to apply, so leave it as-is.
+ return null;
+ }
+ return testHarnessModeData;
+ }
+
private void configureSettings() {
ContentResolver cr = getContext().getContentResolver();
@@ -309,7 +322,14 @@
byte[] adbTempKeysBytes = getBytesFromFile(adbTempKeys);
PersistentData persistentData = new PersistentData(adbKeysBytes, adbTempKeysBytes);
- getPersistentDataBlock().setTestHarnessModeData(persistentData.toBytes());
+ PersistentDataBlockManagerInternal blockManager = getPersistentDataBlock();
+ if (blockManager == null) {
+ Slog.e(TAG, "Failed to enable Test Harness Mode. No implementation of "
+ + "PersistentDataBlockManagerInternal was bound.");
+ getErrPrintWriter().println("Failed to enable Test Harness Mode");
+ return 1;
+ }
+ blockManager.setTestHarnessModeData(persistentData.toBytes());
} catch (IOException e) {
Slog.e(TAG, "Failed to store ADB keys.", e);
getErrPrintWriter().println("Failed to enable Test Harness Mode");
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 6ce42ec..b6a5be8 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -1108,6 +1108,7 @@
// the window manager is still looking for where to put it.
// We will do the work when we get a focus change callback.
// TODO(b/112273690): Support multiple displays
+ // TODO(b/129098348): Support embedded displays
if (mService.getDefaultDisplayContentLocked().mCurrentFocus == null) {
return;
}
@@ -1400,7 +1401,28 @@
if (w.isVisibleLw()) {
outWindows.put(mTempLayer++, w);
}
- }, false /* traverseTopToBottom */ );
+ }, false /* traverseTopToBottom */);
+ mService.mRoot.forAllWindows(w -> {
+ final WindowState win = findRootDisplayParentWindow(w);
+ if (win != null && win.getDisplayContent().isDefaultDisplay && w.isVisibleLw()) {
+ // TODO(b/129098348): insert windows on child displays into outWindows based on
+ // root-display-parent window.
+ outWindows.put(mTempLayer++, w);
+ }
+ }, false /* traverseTopToBottom */);
+ }
+
+ private WindowState findRootDisplayParentWindow(WindowState win) {
+ WindowState displayParentWindow = win.getDisplayContent().getParentWindow();
+ if (displayParentWindow == null) {
+ return null;
+ }
+ WindowState candidate = displayParentWindow;
+ while (candidate != null) {
+ displayParentWindow = candidate;
+ candidate = displayParentWindow.getDisplayContent().getParentWindow();
+ }
+ return displayParentWindow;
}
private class MyHandler extends Handler {
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 0891ba4..feef5e2 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -326,7 +326,7 @@
intent));
}
- if (!isAnyTransitionActive()) {
+ if (mCurrentTransitionStartTime == INVALID_START_TIME) {
mCurrentTransitionStartTime = SystemClock.uptimeMillis();
mLastTransitionStartTime = mCurrentTransitionStartTime;
@@ -965,16 +965,13 @@
* @param info
* */
private void startTraces(WindowingModeTransitionInfo info) {
- if (info == null) {
+ if (!Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER) || info == null
+ || info.launchTraceActive) {
return;
}
- int transitionType = getTransitionType(info);
- if (!info.launchTraceActive && transitionType == TYPE_TRANSITION_WARM_LAUNCH
- || transitionType == TYPE_TRANSITION_COLD_LAUNCH) {
- Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: "
- + info.launchedActivity.packageName, 0);
- info.launchTraceActive = true;
- }
+ Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: "
+ + info.launchedActivity.packageName, 0);
+ info.launchTraceActive = true;
}
private void stopLaunchTrace(WindowingModeTransitionInfo info) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 802683a..1344727 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -120,6 +120,7 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS;
@@ -1631,6 +1632,7 @@
void updateOptionsLocked(ActivityOptions options) {
if (options != null) {
+ if (DEBUG_TRANSITION) Slog.i(TAG, "Update options for " + this);
if (pendingOptions != null) {
pendingOptions.abort();
}
@@ -1641,6 +1643,7 @@
void applyOptionsLocked() {
if (pendingOptions != null
&& pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
+ if (DEBUG_TRANSITION) Slog.i(TAG, "Applying options for " + this);
applyOptionsLocked(pendingOptions, intent);
if (task == null) {
clearOptionsLocked(false /* withAbort */);
@@ -1762,9 +1765,19 @@
pendingOptions = null;
}
- ActivityOptions takeOptionsLocked() {
+ ActivityOptions takeOptionsLocked(boolean fromClient) {
+ if (DEBUG_TRANSITION) Slog.i(TAG, "Taking options for " + this + " callers="
+ + Debug.getCallers(6));
ActivityOptions opts = pendingOptions;
- pendingOptions = null;
+
+ // If we are trying to take activity options from the client, do not null it out if it's a
+ // remote animation as the client doesn't need it ever. This is a workaround when client is
+ // faster to take the options than we are to resume the next activity.
+ // TODO (b/132432864): Fix the root cause of these transition preparing/applying options
+ // timing somehow
+ if (!fromClient || opts == null || opts.getRemoteAnimationAdapter() == null) {
+ pendingOptions = null;
+ }
return opts;
}
@@ -2322,7 +2335,9 @@
return;
}
- if (configChanges == 0 && mAppWindowToken.okToDisplay()) {
+ // Window configuration changes only effect windows, so don't require a screen freeze.
+ int freezableConfigChanges = configChanges & ~(CONFIG_WINDOW_CONFIGURATION);
+ if (freezableConfigChanges == 0 && mAppWindowToken.okToDisplay()) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + appToken);
return;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 8a834c8..3d59e66 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -281,8 +281,9 @@
if (display != null && inSplitScreenPrimaryWindowingMode()) {
// If we created a docked stack we want to resize it so it resizes all other stacks
// in the system.
- getStackDockedModeBounds(null, null, mTmpRect2, mTmpRect3);
- mStackSupervisor.resizeDockedStackLocked(getRequestedOverrideBounds(), mTmpRect2,
+ getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */,
+ mTmpRect /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */);
+ mStackSupervisor.resizeDockedStackLocked(getRequestedOverrideBounds(), mTmpRect,
mTmpRect2, null, null, PRESERVE_WINDOWS);
}
mRootActivityContainer.updateUIDsPresentOnDisplay();
@@ -396,7 +397,6 @@
private final Rect mTmpRect = new Rect();
private final Rect mTmpRect2 = new Rect();
- private final Rect mTmpRect3 = new Rect();
private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic();
/** List for processing through a set of activities */
@@ -512,7 +512,6 @@
mWindowManager = mService.mWindowManager;
mStackId = stackId;
mCurrentUser = mService.mAmInternal.getCurrentUserId();
- mTmpRect2.setEmpty();
// Set display id before setting activity and window type to make sure it won't affect
// stacks on a wrong display.
mDisplayId = display.mDisplayId;
@@ -572,90 +571,87 @@
public void onConfigurationChanged(Configuration newParentConfig) {
final int prevWindowingMode = getWindowingMode();
final boolean prevIsAlwaysOnTop = isAlwaysOnTop();
- final ActivityDisplay display = getDisplay();
final int prevRotation = getWindowConfiguration().getRotation();
final int prevDensity = getConfiguration().densityDpi;
final int prevScreenW = getConfiguration().screenWidthDp;
final int prevScreenH = getConfiguration().screenHeightDp;
-
- getBounds(mTmpRect); // previous bounds
+ final Rect newBounds = mTmpRect;
+ // Initialize the new bounds by previous bounds as the input and output for calculating
+ // override bounds in pinned (pip) or split-screen mode.
+ getBounds(newBounds);
super.onConfigurationChanged(newParentConfig);
- if (display == null) {
- return;
- }
- if (getTaskStack() == null) {
+ final ActivityDisplay display = getDisplay();
+ if (display == null || getTaskStack() == null) {
return;
}
+ final boolean windowingModeChanged = prevWindowingMode != getWindowingMode();
+ final int overrideWindowingMode = getRequestedOverrideWindowingMode();
// Update bounds if applicable
boolean hasNewOverrideBounds = false;
// Use override windowing mode to prevent extra bounds changes if inheriting the mode.
- if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_PINNED) {
+ if (overrideWindowingMode == WINDOWING_MODE_PINNED) {
// Pinned calculation already includes rotation
- mTmpRect2.set(mTmpRect);
- hasNewOverrideBounds = getTaskStack().calculatePinnedBoundsForConfigChange(mTmpRect2);
- } else {
+ hasNewOverrideBounds = getTaskStack().calculatePinnedBoundsForConfigChange(newBounds);
+ } else if (!matchParentBounds()) {
+ // If the parent (display) has rotated, rotate our bounds to best-fit where their
+ // bounds were on the pre-rotated display.
final int newRotation = getWindowConfiguration().getRotation();
- if (!matchParentBounds()) {
- // If the parent (display) has rotated, rotate our bounds to best-fit where their
- // bounds were on the pre-rotated display.
- if (prevRotation != newRotation) {
- mTmpRect2.set(mTmpRect);
- getDisplay().mDisplayContent
- .rotateBounds(newParentConfig.windowConfiguration.getBounds(),
- prevRotation, newRotation, mTmpRect2);
- hasNewOverrideBounds = true;
- }
+ final boolean rotationChanged = prevRotation != newRotation;
+ if (rotationChanged) {
+ display.mDisplayContent.rotateBounds(
+ newParentConfig.windowConfiguration.getBounds(), prevRotation, newRotation,
+ newBounds);
+ hasNewOverrideBounds = true;
+ }
+ // Use override windowing mode to prevent extra bounds changes if inheriting the mode.
+ if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
// If entering split screen or if something about the available split area changes,
// recalculate the split windows to match the new configuration.
- if (prevRotation != newRotation
+ if (rotationChanged || windowingModeChanged
|| prevDensity != getConfiguration().densityDpi
- || prevWindowingMode != getWindowingMode()
|| prevScreenW != getConfiguration().screenWidthDp
|| prevScreenH != getConfiguration().screenHeightDp) {
- // Use override windowing mode to prevent extra bounds changes if inheriting
- // the mode.
- if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- || getRequestedOverrideWindowingMode()
- == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
- mTmpRect2.set(mTmpRect);
- getTaskStack()
- .calculateDockedBoundsForConfigChange(newParentConfig, mTmpRect2);
- hasNewOverrideBounds = true;
- }
+ getTaskStack().calculateDockedBoundsForConfigChange(newParentConfig, newBounds);
+ hasNewOverrideBounds = true;
}
}
}
- if (getWindowingMode() != prevWindowingMode) {
+
+ if (windowingModeChanged) {
// Use override windowing mode to prevent extra bounds changes if inheriting the mode.
- if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
- getStackDockedModeBounds(null, null, mTmpRect2, mTmpRect3);
+ if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */,
+ newBounds /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */);
// immediately resize so docked bounds are available in onSplitScreenModeActivated
setTaskDisplayedBounds(null);
- setTaskBounds(mTmpRect2);
- setBounds(mTmpRect2);
- } else if (
- getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+ setTaskBounds(newBounds);
+ setBounds(newBounds);
+ newBounds.set(newBounds);
+ } else if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
Rect dockedBounds = display.getSplitScreenPrimaryStack().getBounds();
final boolean isMinimizedDock =
- getDisplay().mDisplayContent.getDockedDividerController().isMinimizedDock();
+ display.mDisplayContent.getDockedDividerController().isMinimizedDock();
if (isMinimizedDock) {
TaskRecord topTask = display.getSplitScreenPrimaryStack().topTask();
if (topTask != null) {
dockedBounds = topTask.getBounds();
}
}
- getStackDockedModeBounds(dockedBounds, null, mTmpRect2, mTmpRect3);
+ getStackDockedModeBounds(dockedBounds, null /* currentTempTaskBounds */,
+ newBounds /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */);
hasNewOverrideBounds = true;
}
- }
- if (prevWindowingMode != getWindowingMode()) {
display.onStackWindowingModeChanged(this);
}
if (hasNewOverrideBounds) {
- mRootActivityContainer.resizeStack(this, mTmpRect2, null, null, PRESERVE_WINDOWS,
+ // Note the resizeStack may enter onConfigurationChanged recursively, so we make a copy
+ // of the temporary bounds (newBounds is mTmpRect) to avoid it being modified.
+ mRootActivityContainer.resizeStack(this, new Rect(newBounds), null /* tempTaskBounds */,
+ null /* tempTaskInsetBounds */, PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, true /* deferResume */);
}
if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
@@ -1822,7 +1818,8 @@
prev.setDeferHidingClient(false);
// If we were visible then resumeTopActivities will release resources before
// stopping.
- addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);
+ addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */,
+ "completePauseLocked");
}
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
@@ -1883,8 +1880,11 @@
mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
}
- private void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed) {
+ private void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed,
+ String reason) {
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
+ EventLog.writeEvent(EventLogTags.AM_ADD_TO_STOPPING, r.mUserId,
+ System.identityHashCode(r), r.shortComponentName, reason);
mStackSupervisor.mStoppingActivities.add(r);
}
@@ -2433,7 +2433,7 @@
case PAUSING:
case PAUSED:
addToStopping(r, true /* scheduleIdle */,
- canEnterPictureInPicture /* idleDelayed */);
+ canEnterPictureInPicture /* idleDelayed */, "makeInvisible");
break;
default:
@@ -3051,21 +3051,7 @@
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityInNextFocusableStack: " + reason + ", go home");
- if (isActivityTypeHome()) {
- // resumeTopActivityUncheckedLocked has been prevented to run recursively. Post a
- // runnable to resume home since we are currently in the process of resuming top
- // activity in home stack.
- // See {@link #mInResumeTopActivity}.
- mService.mH.post(
- () -> {
- synchronized (mService.mGlobalLock) {
- mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
- }
- });
- return true;
- } else {
- return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
- }
+ return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
}
/** Returns the position the input task should be placed in this stack. */
@@ -3389,7 +3375,7 @@
canMoveOptions = false;
if (noOptions && topOptions == null) {
- topOptions = p.takeOptionsLocked();
+ topOptions = p.takeOptionsLocked(false /* fromClient */);
if (topOptions != null) {
noOptions = false;
}
@@ -3428,7 +3414,7 @@
}
canMoveOptions = false;
if (noOptions && topOptions == null) {
- topOptions = p.takeOptionsLocked();
+ topOptions = p.takeOptionsLocked(false /* fromClient */);
if (topOptions != null) {
noOptions = false;
}
@@ -4098,7 +4084,8 @@
if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
&& next != null && !next.nowVisible && !isFloating) {
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
- addToStopping(r, false /* scheduleIdle */, false /* idleDelayed */);
+ addToStopping(r, false /* scheduleIdle */, false /* idleDelayed */,
+ "finishCurrentActivityLocked");
}
if (DEBUG_STATES) Slog.v(TAG_STATES,
"Moving to STOPPING: "+ r + " (finish requested)");
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index b8442a8..1cdb49d 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -46,7 +46,6 @@
import android.content.pm.ResolveInfo;
import android.content.pm.SuspendDialogInfo;
import android.content.pm.UserInfo;
-import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -304,7 +303,7 @@
return null;
}
// TODO(b/28935539): should allow certain activities to bypass work challenge
- final IntentSender target = createIntentSenderForOriginalIntent(Binder.getCallingUid(),
+ final IntentSender target = createIntentSenderForOriginalIntent(mCallingUid,
FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT | FLAG_IMMUTABLE);
final KeyguardManager km = (KeyguardManager) mServiceContext
.getSystemService(KEYGUARD_SERVICE);
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index b6840fa..f255048 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -160,6 +160,10 @@
private int mCallingUid;
private ActivityOptions mOptions;
+ // If it is true, background activity can only be started in an existing task that contains
+ // an activity with same uid.
+ private boolean mRestrictedBgActivity;
+
private int mLaunchMode;
private boolean mLaunchTaskBehind;
private int mLaunchFlags;
@@ -455,6 +459,7 @@
mIntent = starter.mIntent;
mCallingUid = starter.mCallingUid;
mOptions = starter.mOptions;
+ mRestrictedBgActivity = starter.mRestrictedBgActivity;
mLaunchTaskBehind = starter.mLaunchTaskBehind;
mLaunchFlags = starter.mLaunchFlags;
@@ -551,7 +556,8 @@
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = r;
mLastStartActivityResult = startActivity(r, sourceRecord, voiceSession, voiceInteractor,
- startFlags, doResume, options, inTask, mLastStartActivityRecord);
+ startFlags, doResume, options, inTask, mLastStartActivityRecord,
+ false /* restrictedBgActivity */);
mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(mLastStartActivityResult,
mLastStartActivityRecord[0]);
return mLastStartActivityResult;
@@ -759,23 +765,20 @@
inTask != null, callerApp, resultRecord, resultStack);
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
+ abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
+ callingPackage);
- boolean abortBackgroundStart = false;
+ boolean restrictedBgActivity = false;
if (!abort) {
try {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"shouldAbortBackgroundActivityStart");
- abortBackgroundStart = shouldAbortBackgroundActivityStart(callingUid,
+ restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
originatingPendingIntent, allowBackgroundActivityStart, intent);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
- abort |= (abortBackgroundStart && !mService.isBackgroundActivityStartsEnabled());
- // TODO: remove this toast after feature development is done
- if (abortBackgroundStart) {
- showBackgroundActivityBlockedToast(abort, callingPackage);
- }
}
// Merge the two options bundles, while realCallerOptions takes precedence.
@@ -918,8 +921,10 @@
|| stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
- mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
- sourceRecord, startFlags, stack, callerApp));
+ if (!restrictedBgActivity) {
+ mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
+ sourceRecord, startFlags, stack, callerApp));
+ }
ActivityOptions.abort(checkedOptions);
return ActivityManager.START_SWITCHES_CANCELED;
}
@@ -929,7 +934,7 @@
mController.doPendingActivityLaunches(false);
final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
- true /* doResume */, checkedOptions, inTask, outActivity);
+ true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity);
mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outActivity[0]);
return res;
}
@@ -939,8 +944,9 @@
WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
boolean allowBackgroundActivityStart, Intent intent) {
// don't abort for the most important UIDs
- if (callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID
- || callingUid == Process.NFC_UID) {
+ final int callingAppId = UserHandle.getAppId(callingUid);
+ if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
+ || callingAppId == Process.NFC_UID) {
return false;
}
// don't abort if the callingUid has a visible window or is a persistent system process
@@ -950,8 +956,8 @@
final boolean isCallingUidForeground = callingUidHasAnyVisibleWindow
|| callingUidProcState == ActivityManager.PROCESS_STATE_TOP
|| callingUidProcState == ActivityManager.PROCESS_STATE_BOUND_TOP;
- final boolean isCallingUidPersistentSystemProcess = (callingUid == Process.SYSTEM_UID)
- || callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
+ final boolean isCallingUidPersistentSystemProcess =
+ callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
if (callingUidHasAnyVisibleWindow || isCallingUidPersistentSystemProcess) {
return false;
}
@@ -966,14 +972,14 @@
? isCallingUidForeground
: realCallingUidHasAnyVisibleWindow
|| realCallingUidProcState == ActivityManager.PROCESS_STATE_TOP;
+ final int realCallingAppId = UserHandle.getAppId(realCallingUid);
final boolean isRealCallingUidPersistentSystemProcess = (callingUid == realCallingUid)
? isCallingUidPersistentSystemProcess
- : (realCallingUid == Process.SYSTEM_UID)
+ : (realCallingAppId == Process.SYSTEM_UID)
|| realCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
if (realCallingUid != callingUid) {
- // don't abort if the realCallingUid has a visible window, unless realCallingUid is
- // SYSTEM_UID, in which case it start needs to be explicitly whitelisted
- if (realCallingUidHasAnyVisibleWindow && realCallingUid != Process.SYSTEM_UID) {
+ // don't abort if the realCallingUid has a visible window
+ if (realCallingUidHasAnyVisibleWindow) {
return false;
}
// if the realCallingUid is a persistent system process, abort if the IntentSender
@@ -1401,13 +1407,13 @@
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
- ActivityRecord[] outActivity) {
+ ActivityRecord[] outActivity, boolean restrictedBgActivity) {
int result = START_CANCELED;
final ActivityStack startedActivityStack;
try {
mService.mWindowManager.deferSurfaceLayout();
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
- startFlags, doResume, options, inTask, outActivity);
+ startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
} finally {
final ActivityStack currentStack = r.getActivityStack();
startedActivityStack = currentStack != null ? currentStack : mTargetStack;
@@ -1443,14 +1449,40 @@
return result;
}
+ /**
+ * Return true if background activity is really aborted.
+ *
+ * TODO(b/131748165): Refactor the logic so we don't need to call this method everywhere.
+ */
+ private boolean handleBackgroundActivityAbort(ActivityRecord r) {
+ // TODO(b/131747138): Remove toast and refactor related code in Q release.
+ boolean abort = !mService.isBackgroundActivityStartsEnabled();
+ showBackgroundActivityBlockedToast(abort, r.launchedFromPackage);
+ if (!abort) {
+ return false;
+ }
+ ActivityRecord resultRecord = r.resultTo;
+ String resultWho = r.resultWho;
+ int requestCode = r.requestCode;
+ if (resultRecord != null) {
+ ActivityStack resultStack = resultRecord.getActivityStack();
+ resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
+ RESULT_CANCELED, null);
+ }
+ // We pretend to the caller that it was really started to make it backward compatible, but
+ // they will just get a cancel result.
+ ActivityOptions.abort(r.pendingOptions);
+ return true;
+ }
+
// Note: This method should only be called from {@link startActivity}.
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
- ActivityRecord[] outActivity) {
-
+ ActivityRecord[] outActivity, boolean restrictedBgActivity) {
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
- voiceInteractor);
+ voiceInteractor, restrictedBgActivity);
+
final int preferredWindowingMode = mLaunchParams.mWindowingMode;
computeLaunchingTaskFlags();
@@ -1658,7 +1690,7 @@
} else {
// This not being started from an existing activity, and not part of a new task...
// just put it in the top task, though these days this case should never happen.
- setTaskToCurrentTopOrCreateNewTask();
+ result = setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) {
return result;
@@ -1731,6 +1763,7 @@
mIntent = null;
mCallingUid = -1;
mOptions = null;
+ mRestrictedBgActivity = false;
mLaunchTaskBehind = false;
mLaunchFlags = 0;
@@ -1770,7 +1803,8 @@
private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
boolean doResume, int startFlags, ActivityRecord sourceRecord,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
+ IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+ boolean restrictedBgActivity) {
reset(false /* clearRequest */);
mStartActivity = r;
@@ -1780,6 +1814,7 @@
mSourceRecord = sourceRecord;
mVoiceSession = voiceSession;
mVoiceInteractor = voiceInteractor;
+ mRestrictedBgActivity = restrictedBgActivity;
mLaunchParams.reset();
@@ -1880,6 +1915,11 @@
}
mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
+
+ if (restrictedBgActivity) {
+ mAvoidMoveToFront = true;
+ mDoResume = false;
+ }
}
private void sendNewTaskResultRequestIfNeeded() {
@@ -2277,6 +2317,9 @@
// isLockTaskModeViolation fails below.
if (mReuseTask == null) {
+ if (mRestrictedBgActivity && handleBackgroundActivityAbort(mStartActivity)) {
+ return START_ABORTED;
+ }
final TaskRecord task = mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId),
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
@@ -2289,6 +2332,11 @@
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in new task " + mStartActivity.getTaskRecord());
} else {
+ if (mRestrictedBgActivity && !mReuseTask.containsAppUid(mCallingUid)) {
+ if (handleBackgroundActivityAbort(mStartActivity)) {
+ return START_ABORTED;
+ }
+ }
addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
}
@@ -2328,6 +2376,12 @@
final TaskRecord sourceTask = mSourceRecord.getTaskRecord();
final ActivityStack sourceStack = mSourceRecord.getActivityStack();
+ if (mRestrictedBgActivity && !sourceTask.containsAppUid(mCallingUid)) {
+ if (handleBackgroundActivityAbort(mStartActivity)) {
+ return START_ABORTED;
+ }
+ return START_ABORTED;
+ }
// We only want to allow changing stack in two cases:
// 1. If the target task is not the top one. Otherwise we would move the launching task to
// the other side, rather than show two side by side.
@@ -2489,20 +2543,33 @@
}
}
- private void setTaskToCurrentTopOrCreateNewTask() {
+ private int setTaskToCurrentTopOrCreateNewTask() {
mTargetStack = computeStackFocus(mStartActivity, false, mLaunchFlags, mOptions);
if (mDoResume) {
mTargetStack.moveToFront("addingToTopTask");
}
final ActivityRecord prev = mTargetStack.getTopActivity();
+ if (mRestrictedBgActivity && prev == null) {
+ if (handleBackgroundActivityAbort(mStartActivity)) {
+ return START_ABORTED;
+ }
+ return START_ABORTED;
+ }
final TaskRecord task = (prev != null)
? prev.getTaskRecord() : mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId), mStartActivity.info,
mIntent, null, null, true, mStartActivity, mSourceRecord, mOptions);
+ if (mRestrictedBgActivity && !task.containsAppUid(mCallingUid)) {
+ if (handleBackgroundActivityAbort(mStartActivity)) {
+ return START_ABORTED;
+ }
+ return START_ABORTED;
+ }
addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
mTargetStack.positionChildWindowContainerAtTop(task);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in new guessed " + mStartActivity.getTaskRecord());
+ return START_SUCCESS;
}
private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 4a6aa33..89962a5 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -141,6 +141,7 @@
import android.app.IApplicationThread;
import android.app.IAssistDataReceiver;
import android.app.INotificationManager;
+import android.app.IRequestFinishCallback;
import android.app.ITaskStackListener;
import android.app.Notification;
import android.app.NotificationManager;
@@ -264,6 +265,7 @@
import com.android.server.appop.AppOpsService;
import com.android.server.firewall.IntentFirewall;
import com.android.server.pm.UserManagerService;
+import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.vr.VrManagerInternal;
@@ -346,6 +348,7 @@
ActivityManagerInternal mAmInternal;
UriGrantsManagerInternal mUgmInternal;
private PackageManagerInternal mPmInternal;
+ private PermissionPolicyInternal mPermissionPolicyInternal;
@VisibleForTesting
final ActivityTaskManagerInternal mInternal;
PowerManagerInternal mPowerManagerInternal;
@@ -1374,6 +1377,9 @@
.setMayWait(userId)
.setIgnoreTargetSecurity(ignoreTargetSecurity)
.setFilterCallingUid(isResolver ? 0 /* system */ : targetUid)
+ // The target may well be in the background, which would normally prevent it
+ // from starting an activity. Here we definitely want the start to succeed.
+ .setAllowBackgroundActivityStart(true)
.execute();
} catch (SecurityException e) {
// XXX need to figure out how to propagate to original app.
@@ -2288,6 +2294,32 @@
}
}
+ @Override
+ public void onBackPressedOnTaskRoot(IBinder token, IRequestFinishCallback callback) {
+ synchronized (mGlobalLock) {
+ ActivityRecord r = ActivityRecord.isInStackLocked(token);
+ if (r == null) {
+ return;
+ }
+ ActivityStack stack = r.getActivityStack();
+ if (stack != null && stack.isSingleTaskInstance()) {
+ // Single-task stacks are used for activities which are presented in floating
+ // windows above full screen activities. Instead of directly finishing the
+ // task, a task change listener is used to notify SystemUI so the action can be
+ // handled specially.
+ final TaskRecord task = r.getTaskRecord();
+ mTaskChangeNotificationController
+ .notifyBackPressedOnTaskRoot(task.getTaskInfo());
+ } else {
+ try {
+ callback.requestFinish();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to invoke request finish callback", e);
+ }
+ }
+ }
+ }
+
/**
* TODO: Add mController hook
*/
@@ -2904,7 +2936,8 @@
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
- final ActivityOptions activityOptions = r.takeOptionsLocked();
+ final ActivityOptions activityOptions = r.takeOptionsLocked(
+ true /* fromClient */);
return activityOptions == null ? null : activityOptions.toBundle();
}
return null;
@@ -5794,6 +5827,13 @@
return mPmInternal;
}
+ PermissionPolicyInternal getPermissionPolicyInternal() {
+ if (mPermissionPolicyInternal == null) {
+ mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
+ }
+ return mPermissionPolicyInternal;
+ }
+
AppWarnings getAppWarningsLocked() {
return mAppWarnings;
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index e053ff3..ddd5c0a 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -452,6 +452,13 @@
void freeze() {
final int transit = mNextAppTransition;
+ // The RemoteAnimationControl didn't register AppTransitionListener and
+ // only initialized the finish and timeout callback when goodToGo().
+ // So cancel the remote animation here to prevent the animation can't do
+ // finish after transition state cleared.
+ if (mRemoteAnimationController != null) {
+ mRemoteAnimationController.cancelAnimation("freeze");
+ }
setAppTransition(TRANSIT_UNSET, 0 /* flags */);
clear();
setReady();
@@ -1902,6 +1909,8 @@
}
void overridePendingAppTransitionRemote(RemoteAnimationAdapter remoteAnimationAdapter) {
+ if (DEBUG_APP_TRANSITIONS) Slog.i(TAG, "Override pending remote transitionSet="
+ + isTransitionSet() + " adapter=" + remoteAnimationAdapter);
if (isTransitionSet()) {
clear();
mNextAppTransitionType = NEXT_TRANSIT_TYPE_REMOTE;
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 75e34fb..d4c4e6a 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -478,7 +478,7 @@
outReasons.put(windowingMode, APP_TRANSITION_WINDOWS_DRAWN);
} else {
outReasons.put(windowingMode,
- wtoken.startingData instanceof SplashScreenStartingData
+ wtoken.mStartingData instanceof SplashScreenStartingData
? APP_TRANSITION_SPLASH_SCREEN
: APP_TRANSITION_SNAPSHOT);
}
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index 6318486..4ceae72 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -129,7 +129,7 @@
mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
new WindowAnimationSpec(anim, position,
mAppToken.getDisplayContent().mAppTransition.canSkipFirstFrame(),
- mAppToken.getWindowCornerRadiusForAnimation()),
+ mAppToken.getDisplayContent().getWindowCornerRadius()),
mAppToken.mWmService.mSurfaceAnimationRunner), false /* hidden */);
}
@@ -195,7 +195,7 @@
}
@Override
- public void onAnimationLeashDestroyed(Transaction t) {
+ public void onAnimationLeashLost(Transaction t) {
// TODO: Once attached to app token, we don't need to hide it immediately if thumbnail
// became visible.
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 8785b01..ecbecba 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -204,7 +204,7 @@
boolean removed;
// Information about an application starting window if displayed.
- StartingData startingData;
+ StartingData mStartingData;
WindowState startingWindow;
StartingSurface startingSurface;
boolean startingDisplayed;
@@ -386,8 +386,8 @@
// it from behind the starting window, so there is no need for it to also be doing its
// own stuff.
win.cancelAnimation();
- removeStartingWindow();
}
+ removeStartingWindow();
updateReportedVisibilityLocked();
}
@@ -509,6 +509,10 @@
final DisplayContent displayContent = getDisplayContent();
displayContent.mOpeningApps.remove(this);
displayContent.mClosingApps.remove(this);
+ if (isInChangeTransition()) {
+ clearChangeLeash(getPendingTransaction(), true /* cancel */);
+ }
+ displayContent.mChangingApps.remove(this);
waitingToShow = false;
hiddenRequested = !visible;
mDeferHidingClient = deferHidingClient;
@@ -875,7 +879,7 @@
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
+ this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
- if (startingData != null) {
+ if (mStartingData != null) {
removeStartingWindow();
}
@@ -1054,7 +1058,7 @@
// If this is the last window and we had requested a starting transition window,
// well there is no point now.
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
- startingData = null;
+ mStartingData = null;
if (mHiddenSetFromTransferredStartingWindow) {
// We set the hidden state to false for the token from a transferred starting window.
// We now reset it back to true since the starting window was the last window in the
@@ -1310,7 +1314,7 @@
void onDisplayChanged(DisplayContent dc) {
DisplayContent prevDc = mDisplayContent;
super.onDisplayChanged(dc);
- if (prevDc == null) {
+ if (prevDc == null || prevDc == mDisplayContent) {
return;
}
if (prevDc.mChangingApps.contains(this)) {
@@ -1333,7 +1337,7 @@
}
}
- if (prevDc != mDisplayContent && mLetterbox != null) {
+ if (mLetterbox != null) {
mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
}
}
@@ -1487,13 +1491,13 @@
final long origId = Binder.clearCallingIdentity();
try {
// Transfer the starting window over to the new token.
- startingData = fromToken.startingData;
+ mStartingData = fromToken.mStartingData;
startingSurface = fromToken.startingSurface;
startingDisplayed = fromToken.startingDisplayed;
fromToken.startingDisplayed = false;
startingWindow = tStartingWindow;
reportedVisible = fromToken.reportedVisible;
- fromToken.startingData = null;
+ fromToken.mStartingData = null;
fromToken.startingSurface = null;
fromToken.startingWindow = null;
fromToken.startingMoved = true;
@@ -1539,13 +1543,13 @@
Binder.restoreCallingIdentity(origId);
}
return true;
- } else if (fromToken.startingData != null) {
+ } else if (fromToken.mStartingData != null) {
// The previous app was getting ready to show a
// starting window, but hasn't yet done so. Steal it!
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
"Moving pending starting from " + fromToken + " to " + this);
- startingData = fromToken.startingData;
- fromToken.startingData = null;
+ mStartingData = fromToken.mStartingData;
+ fromToken.mStartingData = null;
fromToken.startingMoved = true;
scheduleAddStartingWindow();
return true;
@@ -2001,7 +2005,7 @@
}
layoutLetterbox(winHint);
if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
- mLetterbox.applySurfaceChanges(mPendingTransaction);
+ mLetterbox.applySurfaceChanges(getPendingTransaction());
}
}
@@ -2043,7 +2047,7 @@
return false;
}
- if (startingData != null) {
+ if (mStartingData != null) {
return false;
}
@@ -2124,7 +2128,7 @@
}
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
- startingData = new SplashScreenStartingData(mWmService, pkg,
+ mStartingData = new SplashScreenStartingData(mWmService, pkg,
theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
getMergedOverrideConfiguration());
scheduleAddStartingWindow();
@@ -2138,7 +2142,7 @@
}
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
- startingData = new SnapshotStartingData(mWmService, snapshot);
+ mStartingData = new SnapshotStartingData(mWmService, snapshot);
scheduleAddStartingWindow();
return true;
}
@@ -2157,18 +2161,21 @@
@Override
public void run() {
+ // Can be accessed without holding the global lock
+ final StartingData startingData;
synchronized (mWmService.mGlobalLock) {
// There can only be one adding request, silly caller!
mWmService.mAnimationHandler.removeCallbacks(this);
- }
- if (startingData == null) {
- // Animation has been canceled... do nothing.
- if (DEBUG_STARTING_WINDOW) {
- Slog.v(TAG, "startingData was nulled out before handling"
- + " mAddStartingWindow: " + AppWindowToken.this);
+ if (mStartingData == null) {
+ // Animation has been canceled... do nothing.
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG, "startingData was nulled out before handling"
+ + " mAddStartingWindow: " + AppWindowToken.this);
+ }
+ return;
}
- return;
+ startingData = mStartingData;
}
if (DEBUG_STARTING_WINDOW) {
@@ -2186,20 +2193,21 @@
synchronized (mWmService.mGlobalLock) {
// If the window was successfully added, then
// we need to remove it.
- if (removed || startingData == null) {
+ if (removed || mStartingData == null) {
if (DEBUG_STARTING_WINDOW) {
Slog.v(TAG, "Aborted starting " + AppWindowToken.this
- + ": removed=" + removed + " startingData=" + startingData);
+ + ": removed=" + removed + " startingData=" + mStartingData);
}
startingWindow = null;
- startingData = null;
+ mStartingData = null;
abort = true;
} else {
startingSurface = surface;
}
if (DEBUG_STARTING_WINDOW && !abort) {
- Slog.v(TAG, "Added starting " + AppWindowToken.this + ": startingWindow="
- + startingWindow + " startingView=" + startingSurface);
+ Slog.v(TAG,
+ "Added starting " + AppWindowToken.this + ": startingWindow="
+ + startingWindow + " startingView=" + startingSurface);
}
}
if (abort) {
@@ -2246,21 +2254,21 @@
void removeStartingWindow() {
if (startingWindow == null) {
- if (startingData != null) {
+ if (mStartingData != null) {
// Starting window has not been added yet, but it is scheduled to be added.
// Go ahead and cancel the request.
if (DEBUG_STARTING_WINDOW) {
Slog.v(TAG_WM, "Clearing startingData for token=" + this);
}
- startingData = null;
+ mStartingData = null;
}
return;
}
final WindowManagerPolicy.StartingSurface surface;
- if (startingData != null) {
+ if (mStartingData != null) {
surface = startingSurface;
- startingData = null;
+ mStartingData = null;
startingSurface = null;
startingWindow = null;
startingDisplayed = false;
@@ -2553,12 +2561,17 @@
final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
if (a != null) {
+ // Only apply corner radius to animation if we're not in multi window mode.
+ // We don't want rounded corners when in pip or split screen.
+ final float windowCornerRadius = !inMultiWindowMode()
+ ? getDisplayContent().getWindowCornerRadius()
+ : 0;
adapter = new LocalAnimationAdapter(
new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
getDisplayContent().mAppTransition.canSkipFirstFrame(),
appStackClipMode,
true /* isAppAnimation */,
- getWindowCornerRadiusForAnimation()),
+ windowCornerRadius),
mWmService.mSurfaceAnimationRunner);
if (a.getZAdjustment() == Animation.ZORDER_TOP) {
mNeedsZBoost = true;
@@ -2659,8 +2672,8 @@
}
@Override
- public void onAnimationLeashDestroyed(Transaction t) {
- super.onAnimationLeashDestroyed(t);
+ public void onAnimationLeashLost(Transaction t) {
+ super.onAnimationLeashLost(t);
if (mAnimationBoundsLayer != null) {
t.remove(mAnimationBoundsLayer);
mAnimationBoundsLayer = null;
@@ -2846,7 +2859,7 @@
t.reparent(mTransitChangeLeash, null);
mTransitChangeLeash = null;
if (cancel) {
- onAnimationLeashDestroyed(t);
+ onAnimationLeashLost(t);
}
}
@@ -2995,8 +3008,8 @@
pw.print(prefix); pw.print("inPendingTransaction=");
pw.println(inPendingTransaction);
}
- if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
- pw.print(prefix); pw.print("startingData="); pw.print(startingData);
+ if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
+ pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
pw.print(" removed="); pw.print(removed);
pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
pw.print(" mIsExiting="); pw.println(mIsExiting);
@@ -3046,13 +3059,13 @@
if (mSurfaceControl != null) {
if (show && !mLastSurfaceShowing) {
- mPendingTransaction.show(mSurfaceControl);
+ getPendingTransaction().show(mSurfaceControl);
} else if (!show && mLastSurfaceShowing) {
- mPendingTransaction.hide(mSurfaceControl);
+ getPendingTransaction().hide(mSurfaceControl);
}
}
if (mThumbnail != null) {
- mThumbnail.setShowing(mPendingTransaction, show);
+ mThumbnail.setShowing(getPendingTransaction(), show);
}
mLastSurfaceShowing = show;
super.prepareSurfaces();
@@ -3212,8 +3225,8 @@
private void updateColorTransform() {
if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
- mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix,
- mLastAppSaturationInfo.mTranslation);
+ getPendingTransaction().setColorTransform(mSurfaceControl,
+ mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
mWmService.scheduleAnimationLocked();
}
}
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 767327a..e6150cb 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -62,7 +62,7 @@
}
@Override
- public void onAnimationLeashDestroyed(SurfaceControl.Transaction t) {
+ public void onAnimationLeashLost(SurfaceControl.Transaction t) {
}
@Override
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 3f783f6..1e826ee 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -26,6 +26,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
@@ -78,6 +79,8 @@
import static com.android.server.wm.DisplayContentProto.ABOVE_APP_WINDOWS;
import static com.android.server.wm.DisplayContentProto.APP_TRANSITION;
import static com.android.server.wm.DisplayContentProto.BELOW_APP_WINDOWS;
+import static com.android.server.wm.DisplayContentProto.CHANGING_APPS;
+import static com.android.server.wm.DisplayContentProto.CLOSING_APPS;
import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES;
import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO;
import static com.android.server.wm.DisplayContentProto.DOCKED_STACK_DIVIDER_CONTROLLER;
@@ -85,6 +88,7 @@
import static com.android.server.wm.DisplayContentProto.FOCUSED_APP;
import static com.android.server.wm.DisplayContentProto.ID;
import static com.android.server.wm.DisplayContentProto.IME_WINDOWS;
+import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
import static com.android.server.wm.DisplayContentProto.PINNED_STACK_CONTROLLER;
import static com.android.server.wm.DisplayContentProto.ROTATION;
import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
@@ -144,6 +148,7 @@
import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.Matrix;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
@@ -371,6 +376,20 @@
private int mLastKeyguardForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
/**
+ * The maximum aspect ratio (longerSide/shorterSide) that is treated as close-to-square. The
+ * orientation requests from apps would be ignored if the display is close-to-square.
+ */
+ @VisibleForTesting
+ final float mCloseToSquareMaxAspectRatio;
+
+ /**
+ * If this is true, we would not rotate the display for apps. The rotation would be either the
+ * sensor rotation or the user rotation, controlled by
+ * {@link WindowManagerPolicy.UserRotationMode}.
+ */
+ private boolean mIgnoreRotationForApps;
+
+ /**
* Keep track of wallpaper visibility to notify changes.
*/
private boolean mLastWallpaperVisible = false;
@@ -541,6 +560,10 @@
private final InsetsStateController mInsetsStateController;
+ /** @see #getParentWindow() */
+ private WindowState mParentWindow;
+
+ private Point mLocationInParentWindow = new Point();
private SurfaceControl mParentSurfaceControl;
private InputWindowHandle mPortalWindowHandle;
@@ -549,6 +572,9 @@
// Last systemUiVisibility we dispatched to windows.
private int mLastDispatchedSystemUiVisibility = 0;
+ /** Corner radius that windows should have in order to match the display. */
+ private final float mWindowCornerRadius;
+
private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
WindowStateAnimator winAnimator = w.mWinAnimator;
final AppWindowToken atoken = w.mAppToken;
@@ -898,6 +924,8 @@
mDisplayPolicy = new DisplayPolicy(service, this);
mDisplayRotation = new DisplayRotation(service, this);
+ mCloseToSquareMaxAspectRatio = service.mContext.getResources().getFloat(
+ com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio);
if (isDefaultDisplay) {
// The policy may be invoked right after here, so it requires the necessary default
// fields of this display content.
@@ -909,6 +937,7 @@
if (mWmService.mSystemReady) {
mDisplayPolicy.systemReady();
}
+ mWindowCornerRadius = mDisplayPolicy.getWindowCornerRadius();
mDividerControllerLocked = new DockedStackDividerController(service, this);
mPinnedStackControllerLocked = new PinnedStackController(service, this);
@@ -953,6 +982,10 @@
return mDisplayId;
}
+ float getWindowCornerRadius() {
+ return mWindowCornerRadius;
+ }
+
WindowToken getWindowToken(IBinder binder) {
return mTokenMap.get(binder);
}
@@ -1523,6 +1556,21 @@
mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
+
+ // Not much of use to rotate the display for apps since it's close to square.
+ mIgnoreRotationForApps = isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height);
+ }
+
+ private boolean isNonDecorDisplayCloseToSquare(int rotation, int width, int height) {
+ final DisplayCutout displayCutout =
+ calculateDisplayCutoutForRotation(rotation).getDisplayCutout();
+ final int uiMode = mWmService.mPolicy.getUiMode();
+ final int w = mDisplayPolicy.getNonDecorDisplayWidth(
+ width, height, rotation, uiMode, displayCutout);
+ final int h = mDisplayPolicy.getNonDecorDisplayHeight(
+ width, height, rotation, uiMode, displayCutout);
+ final float aspectRatio = Math.max(w, h) / (float) Math.min(w, h);
+ return aspectRatio <= mCloseToSquareMaxAspectRatio;
}
/**
@@ -2103,6 +2151,10 @@
int getOrientation() {
final WindowManagerPolicy policy = mWmService.mPolicy;
+ if (mIgnoreRotationForApps) {
+ return SCREEN_ORIENTATION_USER;
+ }
+
if (mWmService.mDisplayFrozen) {
if (mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
@@ -2723,6 +2775,15 @@
if (mFocusedApp != null) {
mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
}
+ for (int i = mOpeningApps.size() - 1; i >= 0; i--) {
+ mOpeningApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, OPENING_APPS);
+ }
+ for (int i = mClosingApps.size() - 1; i >= 0; i--) {
+ mClosingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CLOSING_APPS);
+ }
+ for (int i = mChangingApps.size() - 1; i >= 0; i--) {
+ mChangingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CHANGING_APPS);
+ }
proto.end(token);
}
@@ -2920,9 +2981,16 @@
forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */);
}
- WindowState findFocusedWindowIfNeeded() {
- return (mWmService.mPerDisplayFocusEnabled
- || mWmService.mRoot.mTopFocusedAppByProcess.isEmpty()) ? findFocusedWindow() : null;
+ /**
+ * Looking for the focused window on this display if the top focused display hasn't been
+ * found yet (topFocusedDisplayId is INVALID_DISPLAY) or per-display focused was allowed.
+ *
+ * @param topFocusedDisplayId Id of the top focused display.
+ * @return The focused window or null if there isn't any or no need to seek.
+ */
+ WindowState findFocusedWindowIfNeeded(int topFocusedDisplayId) {
+ return (mWmService.mPerDisplayFocusEnabled || topFocusedDisplayId == INVALID_DISPLAY)
+ ? findFocusedWindow() : null;
}
WindowState findFocusedWindow() {
@@ -2946,10 +3014,12 @@
* {@link WindowManagerService#UPDATE_FOCUS_WILL_PLACE_SURFACES},
* {@link WindowManagerService#UPDATE_FOCUS_REMOVING_FOCUS}
* @param updateInputWindows Whether to sync the window information to the input module.
+ * @param topFocusedDisplayId Display id of current top focused display.
* @return {@code true} if the focused window has changed.
*/
- boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
- WindowState newFocus = findFocusedWindowIfNeeded();
+ boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows,
+ int topFocusedDisplayId) {
+ WindowState newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId);
if (mCurrentFocus == newFocus) {
return false;
}
@@ -2969,7 +3039,7 @@
if (imWindowChanged) {
mWmService.mWindowsChanged = true;
setLayoutNeeded();
- newFocus = findFocusedWindowIfNeeded();
+ newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId);
}
if (mCurrentFocus != newFocus) {
mWmService.mH.obtainMessage(REPORT_FOCUS_CHANGE, this).sendToTarget();
@@ -3270,7 +3340,7 @@
final SurfaceControl newParent =
shouldAttachToDisplay ? mWindowingLayer : computeImeParent();
if (newParent != null) {
- mPendingTransaction.reparent(mImeWindowsContainers.mSurfaceControl, newParent);
+ getPendingTransaction().reparent(mImeWindowsContainers.mSurfaceControl, newParent);
scheduleAnimation();
}
}
@@ -3677,7 +3747,8 @@
mPortalWindowHandle.touchableRegion.getBounds(mTmpRect);
if (!mTmpBounds.equals(mTmpRect)) {
mPortalWindowHandle.touchableRegion.set(mTmpBounds);
- mPendingTransaction.setInputWindowInfo(mParentSurfaceControl, mPortalWindowHandle);
+ getPendingTransaction().setInputWindowInfo(
+ mParentSurfaceControl, mPortalWindowHandle);
}
}
}
@@ -4776,18 +4847,23 @@
try {
final ScreenRotationAnimation screenRotationAnimation =
mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
+ final Transaction transaction = getPendingTransaction();
if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
screenRotationAnimation.getEnterTransformation().getMatrix().getValues(mTmpFloats);
- mPendingTransaction.setMatrix(mWindowingLayer,
+ transaction.setMatrix(mWindowingLayer,
mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
- mPendingTransaction.setPosition(mWindowingLayer,
+ transaction.setPosition(mWindowingLayer,
mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y]);
- mPendingTransaction.setAlpha(mWindowingLayer,
+ transaction.setAlpha(mWindowingLayer,
screenRotationAnimation.getEnterTransformation().getAlpha());
}
super.prepareSurfaces();
+
+ // TODO: Once we totally eliminate global transaction we will pass transaction in here
+ // rather than merging to global.
+ SurfaceControl.mergeToGlobalTransaction(transaction);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -4916,26 +4992,72 @@
boolean supportsSystemDecorations() {
return (mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this)
|| (mDisplay.getFlags() & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0
- || mWmService.mForceDesktopModeOnExternalDisplays)
+ || (mWmService.mForceDesktopModeOnExternalDisplays && !isUntrustedVirtualDisplay()))
// VR virtual display will be used to run and render 2D app within a VR experience.
&& mDisplayId != mWmService.mVr2dDisplayId;
}
/**
+ * @return {@code true} if the display is non-system created virtual display.
+ */
+ boolean isUntrustedVirtualDisplay() {
+ return mDisplay.getType() == Display.TYPE_VIRTUAL
+ && mDisplay.getOwnerUid() != Process.SYSTEM_UID;
+ }
+
+ /**
* Re-parent the DisplayContent's top surfaces, {@link #mWindowingLayer} and
- * {@link #mOverlayLayer} to the specified surfaceControl.
+ * {@link #mOverlayLayer} to the specified SurfaceControl.
*
+ * @param win The window which owns the SurfaceControl. This indicates the z-order of the
+ * windows of this display against the windows on the parent display.
* @param sc The new SurfaceControl, where the DisplayContent's surfaces will be re-parented to.
*/
- void reparentDisplayContent(SurfaceControl sc) {
+ void reparentDisplayContent(WindowState win, SurfaceControl sc) {
+ mParentWindow = win;
mParentSurfaceControl = sc;
if (mPortalWindowHandle == null) {
mPortalWindowHandle = createPortalWindowHandle(sc.toString());
}
- mPendingTransaction.setInputWindowInfo(sc, mPortalWindowHandle)
+ getPendingTransaction().setInputWindowInfo(sc, mPortalWindowHandle)
.reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc);
}
+ /**
+ * Get the window which owns the surface that this DisplayContent is re-parented to.
+ *
+ * @return the parent window.
+ */
+ WindowState getParentWindow() {
+ return mParentWindow;
+ }
+
+ /**
+ * Update the location of this display in the parent window. This enables windows in this
+ * display to compute the global transformation matrix.
+ *
+ * @param win The parent window of this display.
+ * @param x The x coordinate in the parent window.
+ * @param y The y coordinate in the parent window.
+ */
+ void updateLocation(WindowState win, int x, int y) {
+ if (mParentWindow != win) {
+ throw new IllegalArgumentException(
+ "The given window is not the parent window of this display.");
+ }
+ if (mLocationInParentWindow.x != x || mLocationInParentWindow.y != y) {
+ mLocationInParentWindow.x = x;
+ mLocationInParentWindow.y = y;
+ if (mWmService.mAccessibilityController != null) {
+ mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
+ }
+ }
+ }
+
+ Point getLocationInParentWindow() {
+ return mLocationInParentWindow;
+ }
+
@VisibleForTesting
SurfaceControl getWindowingLayer() {
return mWindowingLayer;
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 32d0b32..197a3cf 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -25,6 +25,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.view.Display.TYPE_BUILT_IN;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.InsetsState.TYPE_TOP_GESTURES;
import static android.view.InsetsState.TYPE_TOP_TAPPABLE_ELEMENT;
@@ -69,6 +70,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
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_SCREENSHOT;
@@ -123,6 +125,7 @@
import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.Region;
import android.hardware.input.InputManager;
import android.hardware.power.V1_0.PowerHint;
import android.os.Handler;
@@ -157,6 +160,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.util.ScreenShapeHelper;
import com.android.internal.util.ScreenshotHelper;
import com.android.internal.util.function.TriConsumer;
@@ -228,7 +232,6 @@
private int mBottomGestureAdditionalInset;
@Px
private int mSideGestureInset;
- private boolean mNavigationBarLetsThroughTaps;
private StatusBarManagerInternal getStatusBarManagerInternal() {
synchronized (mServiceAcquireLock) {
@@ -250,6 +253,9 @@
private volatile boolean mHasNavigationBar;
// Can the navigation bar ever move to the side?
private volatile boolean mNavigationBarCanMove;
+ private volatile boolean mNavigationBarLetsThroughTaps;
+ private volatile boolean mNavigationBarAlwaysShowOnSideGesture;
+ private volatile boolean mAllowSeamlessRotationDespiteNavBarMoving;
// Written by vr manager thread, only read in this class.
private volatile boolean mPersistentVrModeEnabled;
@@ -461,22 +467,31 @@
@Override
public void onSwipeFromBottom() {
- if (mNavigationBar != null
- && mNavigationBarPosition == NAV_BAR_BOTTOM) {
+ if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
requestTransientBars(mNavigationBar);
}
}
@Override
public void onSwipeFromRight() {
- if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) {
+ final Region excludedRegion =
+ mDisplayContent.calculateSystemGestureExclusion();
+ final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
+ || mNavigationBarPosition == NAV_BAR_RIGHT;
+ if (mNavigationBar != null && sideAllowed
+ && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
requestTransientBars(mNavigationBar);
}
}
@Override
public void onSwipeFromLeft() {
- if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) {
+ final Region excludedRegion =
+ mDisplayContent.calculateSystemGestureExclusion();
+ final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
+ || mNavigationBarPosition == NAV_BAR_LEFT;
+ if (mNavigationBar != null && sideAllowed
+ && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
requestTransientBars(mNavigationBar);
}
}
@@ -1994,7 +2009,8 @@
pf.set(displayFrames.mOverscan);
} else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
&& (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW
- || type == TYPE_VOLUME_OVERLAY)) {
+ || type == TYPE_VOLUME_OVERLAY
+ || type == TYPE_KEYGUARD_DIALOG)) {
// Asking for layout as if the nav bar is hidden, lets the application
// extend into the unrestricted overscan screen area. We only do this for
// application windows and certain system windows to ensure no window that
@@ -2694,6 +2710,8 @@
mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
mSideGestureInset = res.getDimensionPixelSize(R.dimen.config_backGestureInset);
mNavigationBarLetsThroughTaps = res.getBoolean(R.bool.config_navBarTapThrough);
+ mNavigationBarAlwaysShowOnSideGesture =
+ res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture);
// This should calculate how much above the frame we accept gestures.
mBottomGestureAdditionalInset = Math.max(0,
@@ -2709,6 +2727,8 @@
mNavigationBarCanMove =
mDisplayContent.mBaseDisplayWidth != mDisplayContent.mBaseDisplayHeight
&& res.getBoolean(R.bool.config_navBarCanMove);
+ mAllowSeamlessRotationDespiteNavBarMoving =
+ res.getBoolean(R.bool.config_allowSeamlessRotationDespiteNavBarMoving);
}
/**
@@ -2718,11 +2738,18 @@
private void updateCurrentUserResources() {
final int userId = mService.mAmInternal.getCurrentUserId();
final Context uiContext = getSystemUiContext();
+
+ if (userId == UserHandle.USER_SYSTEM) {
+ // Skip the (expensive) recreation of resources for the system user below and just
+ // use the resources from the system ui context
+ mCurrentUserResources = uiContext.getResources();
+ return;
+ }
+
+ // For non-system users, ensure that the resources are loaded from the current
+ // user's package info (see ContextImpl.createDisplayContext)
final LoadedApk pi = ActivityThread.currentActivityThread().getPackageInfo(
uiContext.getPackageName(), null, 0, userId);
-
- // Create the resources from the current-user package info
- // (see ContextImpl.createDisplayContext)
mCurrentUserResources = ResourcesManager.getInstance().getResources(null,
pi.getResDir(),
null /* splitResDirs */,
@@ -2870,6 +2897,16 @@
- statusBarHeight;
}
+ /**
+ * Return corner radius in pixels that should be used on windows in order to cover the display.
+ * The radius is only valid for built-in displays since the one who configures window corner
+ * radius cannot know the corner radius of non-built-in display.
+ */
+ float getWindowCornerRadius() {
+ return mDisplayContent.getDisplay().getType() == TYPE_BUILT_IN
+ ? ScreenDecorationsUtils.getWindowCornerRadius(mContext.getResources()) : 0f;
+ }
+
boolean isShowingDreamLw() {
return mShowingDream;
}
@@ -3474,8 +3511,9 @@
}
// If the navigation bar can't change sides, then it will
// jump when we change orientations and we don't rotate
- // seamlessly.
- if (!navigationBarCanMove()) {
+ // seamlessly - unless that is allowed, eg. with gesture
+ // navigation where the navbar is low-profile enough that this isn't very noticeable.
+ if (!navigationBarCanMove() && !mAllowSeamlessRotationDespiteNavBarMoving) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 34a4802..282ed42 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -39,7 +39,6 @@
import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;
-import android.view.DisplayCutout;
import android.view.Surface;
import com.android.internal.annotations.VisibleForTesting;
@@ -74,8 +73,6 @@
private final int mDeskDockRotation;
private final int mUndockedHdmiRotation;
- private final float mCloseToSquareMaxAspectRatio;
-
private OrientationListener mOrientationListener;
private StatusBarManagerInternal mStatusBarManagerInternal;
private SettingsObserver mSettingsObserver;
@@ -163,9 +160,6 @@
mUndockedHdmiRotation = readRotation(
com.android.internal.R.integer.config_undockedHdmiRotation);
- mCloseToSquareMaxAspectRatio = mContext.getResources().getFloat(
- com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio);
-
if (isDefaultDisplay) {
final Handler uiHandler = UiThread.getHandler();
mOrientationListener = new OrientationListener(mContext, uiHandler);
@@ -242,31 +236,16 @@
// It's also not likely to rotate a TV screen.
final boolean isTv = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK);
- // Not much of use to rotate the display since it's close to square.
- final boolean isCloseToSquare =
- isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height);
final boolean forceDesktopMode =
mService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay;
mDefaultFixedToUserRotation =
- (isCar || isTv || mService.mIsPc || forceDesktopMode || isCloseToSquare)
+ (isCar || isTv || mService.mIsPc || forceDesktopMode)
// For debug purposes the next line turns this feature off with:
// $ adb shell setprop config.override_forced_orient true
// $ adb shell wm size reset
&& !"true".equals(SystemProperties.get("config.override_forced_orient"));
}
- private boolean isNonDecorDisplayCloseToSquare(int rotation, int width, int height) {
- final DisplayCutout displayCutout =
- mDisplayContent.calculateDisplayCutoutForRotation(rotation).getDisplayCutout();
- final int uiMode = mService.mPolicy.getUiMode();
- final int w = mDisplayPolicy.getNonDecorDisplayWidth(
- width, height, rotation, uiMode, displayCutout);
- final int h = mDisplayPolicy.getNonDecorDisplayHeight(
- width, height, rotation, uiMode, displayCutout);
- final float aspectRatio = Math.max(w, h) / (float) Math.min(w, h);
- return aspectRatio <= mCloseToSquareMaxAspectRatio;
- }
-
void setRotation(int rotation) {
if (mOrientationListener != null) {
mOrientationListener.setCurrentRotation(rotation);
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index df36b09..169f03b 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -133,27 +133,33 @@
* Update the Keyguard showing state.
*/
void setKeyguardShown(boolean keyguardShowing, boolean aodShowing) {
- boolean showingChanged = keyguardShowing != mKeyguardShowing || aodShowing != mAodShowing;
// If keyguard is going away, but SystemUI aborted the transition, need to reset state.
- showingChanged |= mKeyguardGoingAway && keyguardShowing;
- if (!showingChanged) {
+ final boolean keyguardChanged = keyguardShowing != mKeyguardShowing
+ || mKeyguardGoingAway && keyguardShowing;
+ final boolean aodChanged = aodShowing != mAodShowing;
+ if (!keyguardChanged && !aodChanged) {
return;
}
mKeyguardShowing = keyguardShowing;
mAodShowing = aodShowing;
mWindowManager.setAodShowing(aodShowing);
- if (showingChanged) {
+
+ if (keyguardChanged) {
+ // Irrelevant to AOD.
dismissDockedStackIfNeeded();
setKeyguardGoingAway(false);
- // TODO(b/113840485): Check usage for non-default display
- mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay(
- isKeyguardOrAodShowing(DEFAULT_DISPLAY));
if (keyguardShowing) {
mDismissalRequested = false;
}
}
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ // TODO(b/113840485): Check usage for non-default display
+ mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay(
+ isKeyguardOrAodShowing(DEFAULT_DISPLAY));
+
+ // Update the sleep token first such that ensureActivitiesVisible has correct sleep token
+ // state when evaluating visibilities.
updateKeyguardSleepToken();
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
/**
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 2411e00..ef2a21d 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -802,18 +802,24 @@
* leaves the pinned mode.
*/
private void lockKeyguardIfNeeded() {
+ if (shouldLockKeyguard()) {
+ mWindowManager.lockNow(null);
+ mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
+ getLockPatternUtils().requireCredentialEntry(USER_ALL);
+ }
+ }
+
+ private boolean shouldLockKeyguard() {
+ // This functionality should be kept consistent with
+ // com.android.settings.security.ScreenPinningSettings (see b/127605586)
try {
- boolean shouldLockKeyguard = Settings.Secure.getIntForUser(
+ return Settings.Secure.getIntForUser(
mContext.getContentResolver(),
- Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
- USER_CURRENT) != 0;
- if (shouldLockKeyguard) {
- mWindowManager.lockNow(null);
- mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
- getLockPatternUtils().requireCredentialEntry(USER_ALL);
- }
+ Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, USER_CURRENT) != 0;
} catch (Settings.SettingNotFoundException e) {
- // No setting, don't lock.
+ // Log to SafetyNet for b/127605586
+ android.util.EventLog.writeEvent(0x534e4554, "127605586", -1, "");
+ return mLockPatternUtils.isSecure(USER_CURRENT);
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 07d3fb9..f82fdba 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -60,6 +60,12 @@
private final ActivityDisplay mDefaultDisplay;
private final int mCallingPid;
+ /**
+ * The activity which has been launched behind. We need to remember the activity because the
+ * target stack may have other activities, then we are able to restore the launch-behind state
+ * for the exact activity.
+ */
+ private ActivityRecord mLaunchedTargetActivity;
private int mTargetActivityType;
// The stack to restore the target stack behind when the animation is finished
@@ -175,6 +181,7 @@
// Mark the target activity as launch-behind to bump its visibility for the
// duration of the gesture that is driven by the recents component
targetActivity.mLaunchTaskBehind = true;
+ mLaunchedTargetActivity = targetActivity;
// Fetch all the surface controls and pass them to the client to get the animation
// started. Cancel any existing recents animation running synchronously (do not hold the
@@ -213,7 +220,9 @@
// Unregister for stack order changes
mDefaultDisplay.unregisterStackOrderChangedListener(this);
- if (mWindowManager.getRecentsAnimationController() == null) return;
+ final RecentsAnimationController controller =
+ mWindowManager.getRecentsAnimationController();
+ if (controller == null) return;
// Just to be sure end the launch hint in case the target activity was never launched.
// However, if we're keeping the activity and making it visible, we can leave it on.
@@ -233,8 +242,10 @@
final ActivityStack targetStack = mDefaultDisplay.getStack(
WINDOWING_MODE_UNDEFINED, mTargetActivityType);
+ // Prefer to use the original target activity instead of top activity because
+ // we may have moved another task to top (starting 3p launcher).
final ActivityRecord targetActivity = targetStack != null
- ? targetStack.getTopActivity()
+ ? targetStack.isInStackLocked(mLaunchedTargetActivity)
: null;
if (DEBUG) Slog.d(TAG, "onAnimationFinished(): targetStack=" + targetStack
+ " targetActivity=" + targetActivity
@@ -283,6 +294,16 @@
}
}
} else {
+ // If there is no recents screenshot animation, we can update the visibility
+ // of target stack immediately because it is visually invisible and the
+ // launch-behind state is restored. That also prevents the next transition
+ // type being disturbed if the visibility is updated after setting the next
+ // transition (the target activity will be one of closing apps).
+ if (!controller.shouldCancelWithDeferredScreenshot()
+ && !targetStack.isFocusedStackOnDisplay()) {
+ targetStack.ensureActivitiesVisibleLocked(null /* starting */,
+ 0 /* starting */, false /* preserveWindows */);
+ }
// Keep target stack in place, nothing changes, so ignore the transition
// logic below
return;
@@ -331,6 +352,10 @@
}
final RecentsAnimationController controller =
mWindowManager.getRecentsAnimationController();
+ if (controller == null) {
+ return;
+ }
+
final DisplayContent dc =
mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
dc.mBoundsAnimationController.setAnimationType(
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 5f95691..b4bfedd 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -132,7 +132,7 @@
sendRunningRemoteAnimation(true);
}
- private void cancelAnimation(String reason) {
+ void cancelAnimation(String reason) {
if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "cancelAnimation(): reason=" + reason);
synchronized (mService.getWindowManagerLock()) {
if (mCanceled) {
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index e65a241..3ec461d 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -1174,8 +1174,9 @@
resumedOnDisplay |= result;
continue;
}
- if (topRunningActivity.isState(RESUMED)) {
- // Kick off any lingering app transitions form the MoveTaskToFront operation.
+ if (display.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
+ // Kick off any lingering app transitions form the MoveTaskToFront operation,
+ // but only consider the top task and stack on that display.
stack.executeAppTransition(targetOptions);
} else {
resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 9f42324..8a5f52f 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -170,7 +170,7 @@
int topFocusedDisplayId = INVALID_DISPLAY;
for (int i = mChildren.size() - 1; i >= 0; --i) {
final DisplayContent dc = mChildren.get(i);
- changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows);
+ changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows, topFocusedDisplayId);
final WindowState newFocus = dc.mCurrentFocus;
if (newFocus != null) {
final int pidOfNewFocus = newFocus.mSession.mPid;
@@ -180,6 +180,11 @@
if (topFocusedDisplayId == INVALID_DISPLAY) {
topFocusedDisplayId = dc.getDisplayId();
}
+ } else if (topFocusedDisplayId == INVALID_DISPLAY && dc.mFocusedApp != null) {
+ // The top-most display that has a focused app should still be the top focused
+ // display even when the app window is not ready yet (process not attached or
+ // window not added yet).
+ topFocusedDisplayId = dc.getDisplayId();
}
}
if (topFocusedDisplayId == INVALID_DISPLAY) {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index b33f8c7..34273f3 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -426,6 +426,16 @@
}
@Override
+ public void reparentDisplayContent(IWindow window, SurfaceControl sc, int displayId) {
+ mService.reparentDisplayContent(window, sc, displayId);
+ }
+
+ @Override
+ public void updateDisplayContentLocation(IWindow window, int x, int y, int displayId) {
+ mService.updateDisplayContentLocation(window, x, y, displayId);
+ }
+
+ @Override
public void updateTapExcludeRegion(IWindow window, int regionId, Region region) {
final long identity = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index b3b41b7..3d9dfeb 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -50,7 +50,8 @@
@VisibleForTesting
SurfaceControl mLeash;
- private final Animatable mAnimatable;
+ @VisibleForTesting
+ final Animatable mAnimatable;
private final OnAnimationFinishedCallback mInnerAnimationFinishedCallback;
@VisibleForTesting
final Runnable mAnimationFinishedCallback;
@@ -282,13 +283,15 @@
boolean scheduleAnim = false;
- // If the surface was destroyed, we don't care to reparent it back.
- final boolean destroy = mLeash != null && surface != null && parent != null;
- if (destroy) {
- if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to original parent");
+ // If the surface was destroyed or the leash is invalid, we don't care to reparent it back.
+ // Note that we also set this variable to true even if the parent isn't valid anymore, in
+ // order to ensure onAnimationLeashLost still gets called in this case.
+ final boolean reparent = mLeash != null && surface != null;
+ if (reparent) {
+ if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to original parent: " + parent);
// We shouldn't really need these isValid checks but we do
// b/130364451
- if (surface.isValid() && parent.isValid()) {
+ if (surface.isValid() && parent != null && parent.isValid()) {
t.reparent(surface, parent);
scheduleAnim = true;
}
@@ -301,9 +304,10 @@
mLeash = null;
mAnimation = null;
- // Make sure to inform the animatable after the leash was destroyed.
- if (destroy) {
- mAnimatable.onAnimationLeashDestroyed(t);
+ if (reparent) {
+ // Make sure to inform the animatable after the surface was reparented (or reparent
+ // wasn't possible, but we still need to invoke the callback)
+ mAnimatable.onAnimationLeashLost(t);
scheduleAnim = true;
}
@@ -394,12 +398,12 @@
void onAnimationLeashCreated(Transaction t, SurfaceControl leash);
/**
- * Called when the leash is being destroyed, and the surface was reparented back to the
- * original parent.
+ * Called when the leash is being destroyed, or when the leash is being transferred to
+ * another SurfaceAnimator.
*
* @param t The transaction to use to apply any necessary changes.
*/
- void onAnimationLeashDestroyed(Transaction t);
+ void onAnimationLeashLost(Transaction t);
/**
* @return A new surface to be used for the animation leash, inserted at the correct
diff --git a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
index 35afaed..854537b 100644
--- a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.graphics.Rect;
+import android.graphics.Region;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Handler;
import android.os.SystemClock;
@@ -201,6 +202,10 @@
}
}
+ protected boolean currentGestureStartedInRegion(Region r) {
+ return r.contains((int) mDownX[0], (int) mDownY[0]);
+ }
+
private int findIndex(int pointerId) {
for (int i = 0; i < mDownPointers; i++) {
if (mDownPointerId[i] == pointerId) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index bb7867c..3820106 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -138,6 +138,7 @@
setOrientation(SCREEN_ORIENTATION_UNSET);
}
+ @Override
DisplayContent getDisplayContent() {
return mStack != null ? mStack.getDisplayContent() : null;
}
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 3d57219..66200e3 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -53,6 +53,7 @@
private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG = 19;
private static final int NOTIFY_SIZE_COMPAT_MODE_ACTIVITY_CHANGED_MSG = 20;
+ private static final int NOTIFY_BACK_PRESSED_ON_TASK_ROOT = 21;
// Delay in notifying task stack change listeners (in millis)
private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -92,6 +93,10 @@
l.onTaskDescriptionChanged((RunningTaskInfo) m.obj);
};
+ private final TaskStackConsumer mNotifyBackPressedOnTaskRoot = (l, m) -> {
+ l.onBackPressedOnTaskRoot((RunningTaskInfo) m.obj);
+ };
+
private final TaskStackConsumer mNotifyActivityRequestedOrientationChanged = (l, m) -> {
l.onActivityRequestedOrientationChanged(m.arg1, m.arg2);
};
@@ -225,6 +230,9 @@
case NOTIFY_SIZE_COMPAT_MODE_ACTIVITY_CHANGED_MSG:
forAllRemoteListeners(mOnSizeCompatModeActivityChanged, msg);
break;
+ case NOTIFY_BACK_PRESSED_ON_TASK_ROOT:
+ forAllRemoteListeners(mNotifyBackPressedOnTaskRoot, msg);
+ break;
}
}
}
@@ -458,4 +466,15 @@
forAllLocalListeners(mOnSizeCompatModeActivityChanged, msg);
msg.sendToTarget();
}
+
+ /**
+ * Notify listeners that an activity received a back press when there are no other activities
+ * in the back stack.
+ */
+ void notifyBackPressedOnTaskRoot(TaskInfo taskInfo) {
+ final Message msg = mHandler.obtainMessage(NOTIFY_BACK_PRESSED_ON_TASK_ROOT,
+ taskInfo);
+ forAllLocalListeners(mNotifyBackPressedOnTaskRoot, msg);
+ msg.sendToTarget();
+ }
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index d4d157fb..298b302 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -1161,6 +1161,19 @@
return false;
}
+ /**
+ * Return true if any activities in this task belongs to input uid.
+ */
+ boolean containsAppUid(int uid) {
+ for (int i = mActivities.size() - 1; i >= 0; --i) {
+ final ActivityRecord r = mActivities.get(i);
+ if (r.getUid() == uid) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
if (mStack != null) {
for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
@@ -1480,7 +1493,7 @@
if (r.finishing) {
continue;
}
- ActivityOptions opts = r.takeOptionsLocked();
+ ActivityOptions opts = r.takeOptionsLocked(false /* fromClient */);
if (opts != null) {
ret.updateOptionsLocked(opts);
}
diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
index f47e794..ee4e462 100644
--- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
+++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
@@ -77,7 +77,7 @@
@Override
public SurfaceControl.Transaction getPendingTransaction() {
- return mTask.mPendingTransaction;
+ return mTask.getPendingTransaction();
}
@Override
@@ -91,9 +91,11 @@
}
@Override
- public void onAnimationLeashDestroyed(SurfaceControl.Transaction t) {
- t.remove(mSurfaceControl);
- mSurfaceControl = null;
+ public void onAnimationLeashLost(SurfaceControl.Transaction t) {
+ if (mSurfaceControl != null) {
+ t.remove(mSurfaceControl);
+ mSurfaceControl = null;
+ }
}
@Override
@@ -113,7 +115,7 @@
@Override
public SurfaceControl getParentSurfaceControl() {
- return mTask.mSurfaceAnimator.mLeash;
+ return mTask.mSurfaceControl;
}
@Override
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 7515b3f..ab5e071 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -93,10 +93,6 @@
/** Unique identifier */
final int mStackId;
- /** The display this stack sits under. */
- // TODO: Track parent marks like this in WindowContainer.
- private DisplayContent mDisplayContent;
-
/** For comparison with DisplayContent bounds. */
private Rect mTmpRect = new Rect();
private Rect mTmpRect2 = new Rect();
@@ -177,10 +173,6 @@
EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
}
- DisplayContent getDisplayContent() {
- return mDisplayContent;
- }
-
Task findHomeTask() {
if (!isActivityTypeHome() || mChildren.isEmpty()) {
return null;
@@ -805,7 +797,12 @@
if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
return;
}
- transaction.setWindowCrop(mSurfaceControl, width, height);
+ if (getWindowConfiguration().tasksAreFloating()) {
+ // Don't crop freeform windows to the stack.
+ transaction.setWindowCrop(mSurfaceControl, -1, -1);
+ } else {
+ transaction.setWindowCrop(mSurfaceControl, width, height);
+ }
mLastSurfaceSize.set(width, height);
}
@@ -820,8 +817,7 @@
throw new IllegalStateException("onDisplayChanged: Already attached");
}
- final boolean movedToNewDisplay = mDisplayContent == null;
- mDisplayContent = dc;
+ super.onDisplayChanged(dc);
updateSurfaceBounds();
if (mAnimationBackgroundSurface == null) {
@@ -829,8 +825,6 @@
.setName("animation background stackId=" + mStackId)
.build();
}
-
- super.onDisplayChanged(dc);
}
/**
@@ -1627,21 +1621,6 @@
@Override // AnimatesBounds
public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
boolean moveToFullscreen) {
- if (mAnimationType == BoundsAnimationController.FADE_IN) {
- setPinnedStackAlpha(1f);
- try {
- mWmService.mActivityTaskManager.notifyPinnedStackAnimationEnded();
- } catch (RemoteException e) {
- // I don't believe you...
- }
- return;
- }
-
- onBoundAnimationEnd(schedulePipModeChangedCallback, finalStackSize, moveToFullscreen);
- }
-
- private void onBoundAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
- boolean moveToFullscreen) {
if (inPinnedWindowingMode()) {
// Update to the final bounds if requested. This is done here instead of in the bounds
// animator to allow us to coordinate this after we notify the PiP mode changed
@@ -1653,6 +1632,11 @@
mBoundsAnimationTarget, false /* forceUpdate */);
}
+ if (mAnimationType == BoundsAnimationController.FADE_IN) {
+ setPinnedStackAlpha(1f);
+ mActivityStack.mService.notifyPinnedStackAnimationEnded();
+ }
+
if (finalStackSize != null && !mCancelCurrentBoundsAnimation) {
setPinnedStackSize(finalStackSize, null);
} else {
@@ -1661,14 +1645,9 @@
onPipAnimationEndResize();
}
- try {
- mWmService.mActivityTaskManager.notifyPinnedStackAnimationEnded();
- if (moveToFullscreen) {
- mWmService.mActivityTaskManager.moveTasksToFullscreenStack(mStackId,
- true /* onTop */);
- }
- } catch (RemoteException e) {
- // I don't believe you...
+ mActivityStack.mService.notifyPinnedStackAnimationEnded();
+ if (moveToFullscreen) {
+ mActivityStack.mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
}
} else {
// No PiP animation, just run the normal animation-end logic
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index f3f6397..bbef261 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -109,14 +109,19 @@
// The owner/creator for this container. No controller if null.
WindowContainerController mController;
+ // The display this window container is on.
+ protected DisplayContent mDisplayContent;
+
protected SurfaceControl mSurfaceControl;
private int mLastLayer = 0;
private SurfaceControl mLastRelativeToLayer = null;
+ // TODO(b/132320879): Remove this from WindowContainers except DisplayContent.
+ private final Transaction mPendingTransaction;
+
/**
* Applied as part of the animation pass in "prepareSurfaces".
*/
- protected final Transaction mPendingTransaction;
protected final SurfaceAnimator mSurfaceAnimator;
protected final WindowManagerService mWmService;
@@ -320,12 +325,12 @@
}
if (mSurfaceControl != null) {
- mPendingTransaction.remove(mSurfaceControl);
+ getPendingTransaction().remove(mSurfaceControl);
// Merge to parent transaction to ensure the transactions on this WindowContainer are
// applied in native even if WindowContainer is removed.
if (mParent != null) {
- mParent.getPendingTransaction().merge(mPendingTransaction);
+ mParent.getPendingTransaction().merge(getPendingTransaction());
}
mSurfaceControl = null;
@@ -508,12 +513,20 @@
* @param dc The display this container is on after changes.
*/
void onDisplayChanged(DisplayContent dc) {
+ mDisplayContent = dc;
+ if (dc != null && dc != this) {
+ dc.getPendingTransaction().merge(mPendingTransaction);
+ }
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer child = mChildren.get(i);
child.onDisplayChanged(dc);
}
}
+ DisplayContent getDisplayContent() {
+ return mDisplayContent;
+ }
+
void setWaitingForDrawnIfResizingChanged() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer wc = mChildren.get(i);
@@ -1180,13 +1193,7 @@
}
}
- /**
- * TODO: Once we totally eliminate global transaction we will pass transaction in here
- * rather than merging to global.
- */
void prepareSurfaces() {
- SurfaceControl.mergeToGlobalTransaction(getPendingTransaction());
-
// If a leash has been set when the transaction was committed, then the leash reparent has
// been committed.
mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
@@ -1204,8 +1211,8 @@
}
/**
- * Trigger a call to prepareSurfaces from the animation thread, such that
- * mPendingTransaction will be applied.
+ * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
+ * will be applied.
*/
void scheduleAnimation() {
if (mParent != null) {
@@ -1224,6 +1231,14 @@
@Override
public Transaction getPendingTransaction() {
+ final DisplayContent displayContent = getDisplayContent();
+ if (displayContent != null && displayContent != this) {
+ return displayContent.getPendingTransaction();
+ }
+ // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we
+ // let the caller to save the surface operations within the local mPendingTransaction.
+ // If this is not a DisplayContent, we will merge it to the pending transaction of its
+ // display once it attaches to it.
return mPendingTransaction;
}
@@ -1290,7 +1305,7 @@
}
@Override
- public void onAnimationLeashDestroyed(Transaction t) {
+ public void onAnimationLeashLost(Transaction t) {
mLastLayer = -1;
reassignLayer(t);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4f849cd..47df839 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -35,7 +35,6 @@
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.Display.TYPE_VIRTUAL;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
@@ -138,6 +137,7 @@
import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.Matrix;
+import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -164,7 +164,6 @@
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
-import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -240,7 +239,6 @@
import com.android.internal.os.IResultReceiver;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
-import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.LatencyTracker;
@@ -793,9 +791,6 @@
final DisplayManager mDisplayManager;
final ActivityTaskManagerService mAtmService;
- /** Corner radius that windows should have in order to match the display. */
- final float mWindowCornerRadius;
-
/** Indicates whether this device supports wide color gamut / HDR rendering */
private boolean mHasWideColorGamutSupport;
private boolean mHasHdrSupport;
@@ -1020,7 +1015,6 @@
mInputManager = inputManager; // Must be before createDisplayContentLocked.
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mDisplayWindowSettings = new DisplayWindowSettings(this);
- mWindowCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context.getResources());
mTransactionFactory = transactionFactory;
mTransaction = mTransactionFactory.make();
@@ -1880,7 +1874,8 @@
// We need to report touchable region changes to accessibility.
if (mAccessibilityController != null
- && w.getDisplayContent().getDisplayId() == DEFAULT_DISPLAY) {
+ && (w.getDisplayContent().getDisplayId() == DEFAULT_DISPLAY
+ || w.getDisplayContent().getParentWindow() != null)) {
mAccessibilityController.onSomeWindowResizedOrMovedLocked();
}
}
@@ -2012,7 +2007,8 @@
}
if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
&& (mAccessibilityController != null)
- && (win.getDisplayId() == DEFAULT_DISPLAY)) {
+ && (win.getDisplayId() == DEFAULT_DISPLAY
+ || win.getDisplayContent().getParentWindow() != null)) {
// No move or resize, but the controller checks for title changes as well
mAccessibilityController.onSomeWindowResizedOrMovedLocked();
}
@@ -2609,9 +2605,11 @@
final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
if (wtoken != null) {
final WindowState win = wtoken.findMainWindow();
- if (win != null) {
- win.mWinAnimator.setOpaqueLocked(isOpaque);
+ if (win == null) {
+ return;
}
+ isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
+ win.mWinAnimator.setOpaqueLocked(isOpaque);
}
}
@@ -6703,6 +6701,61 @@
}
}
+ private void checkCallerOwnsDisplay(int displayId) {
+ final Display display = mDisplayManager.getDisplay(displayId);
+ if (display == null) {
+ throw new IllegalArgumentException(
+ "Cannot find display for non-existent displayId: " + displayId);
+ }
+
+ final int callingUid = Binder.getCallingUid();
+ final int displayOwnerUid = display.getOwnerUid();
+ if (callingUid != displayOwnerUid) {
+ throw new SecurityException("The caller doesn't own the display.");
+ }
+ }
+
+ /** @see Session#reparentDisplayContent(IWindow, SurfaceControl, int) */
+ void reparentDisplayContent(IWindow client, SurfaceControl sc, int displayId) {
+ checkCallerOwnsDisplay(displayId);
+
+ synchronized (mGlobalLock) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final WindowState win = windowForClientLocked(null, client, false);
+ if (win == null) {
+ Slog.w(TAG_WM, "Bad requesting window " + client);
+ return;
+ }
+ getDisplayContentOrCreate(displayId, null).reparentDisplayContent(win, sc);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ /** @see Session#updateDisplayContentLocation(IWindow, int, int, int) */
+ void updateDisplayContentLocation(IWindow client, int x, int y, int displayId) {
+ checkCallerOwnsDisplay(displayId);
+
+ synchronized (mGlobalLock) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final WindowState win = windowForClientLocked(null, client, false);
+ if (win == null) {
+ Slog.w(TAG_WM, "Bad requesting window " + client);
+ return;
+ }
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+ if (displayContent != null) {
+ displayContent.updateLocation(win, x, y);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
/**
* Update a tap exclude region in the window identified by the provided id. Touches down on this
* region will not:
@@ -6778,9 +6831,26 @@
return;
}
+ int lastWindowingMode = displayContent.getWindowingMode();
mDisplayWindowSettings.setWindowingModeLocked(displayContent, mode);
reconfigureDisplayLocked(displayContent);
+
+ if (lastWindowingMode != displayContent.getWindowingMode()) {
+ // reconfigure won't detect this change in isolation because the windowing mode is
+ // already set on the display, so fire off a new config now.
+ mH.removeMessages(H.SEND_NEW_CONFIGURATION);
+
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ // direct call since lock is shared.
+ sendNewConfiguration(displayId);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ // Now that all configurations are updated, execute pending transitions
+ displayContent.executeAppTransition();
+ }
}
}
@@ -6873,21 +6943,13 @@
+ "not exist: " + displayId);
return false;
}
- final Display display = displayContent.getDisplay();
- if (isUntrustedVirtualDisplay(display)) {
+ if (displayContent.isUntrustedVirtualDisplay()) {
return false;
}
return displayContent.supportsSystemDecorations();
}
}
- /**
- * @return {@code true} if the display is non-system created virtual display.
- */
- private static boolean isUntrustedVirtualDisplay(Display display) {
- return display.getType() == TYPE_VIRTUAL && display.getOwnerUid() != Process.SYSTEM_UID;
- }
-
@Override
public void setShouldShowSystemDecors(int displayId, boolean shouldShow) {
if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setShouldShowSystemDecors()")) {
@@ -6901,6 +6963,10 @@
+ "not exist: " + displayId);
return;
}
+ if (displayContent.isUntrustedVirtualDisplay()) {
+ throw new SecurityException("Attempted to set system decors flag to an untrusted "
+ + "virtual display: " + displayId);
+ }
mDisplayWindowSettings.setShouldShowSystemDecorsLocked(displayContent, shouldShow);
@@ -6921,8 +6987,7 @@
+ displayId);
return false;
}
- final Display display = displayContent.getDisplay();
- if (isUntrustedVirtualDisplay(display)) {
+ if (displayContent.isUntrustedVirtualDisplay()) {
return false;
}
return mDisplayWindowSettings.shouldShowImeLocked(displayContent)
@@ -6943,6 +7008,10 @@
+ displayId);
return;
}
+ if (displayContent.isUntrustedVirtualDisplay()) {
+ throw new SecurityException("Attempted to set IME flag to an untrusted "
+ + "virtual display: " + displayId);
+ }
mDisplayWindowSettings.setShouldShowImeLocked(displayContent, shouldShow);
@@ -7374,8 +7443,7 @@
@Override
public boolean shouldShowIme(int displayId) {
synchronized (mGlobalLock) {
- final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
- return mDisplayWindowSettings.shouldShowImeLocked(displayContent);
+ return WindowManagerService.this.shouldShowIme(displayId);
}
}
}
@@ -7538,31 +7606,6 @@
}
@Override
- public void reparentDisplayContent(int displayId, SurfaceControl sc) {
- final Display display = mDisplayManager.getDisplay(displayId);
- if (display == null) {
- throw new IllegalArgumentException(
- "Can't reparent display for non-existent displayId: " + displayId);
- }
-
- final int callingUid = Binder.getCallingUid();
- final int displayOwnerUid = display.getOwnerUid();
- if (callingUid != displayOwnerUid) {
- throw new SecurityException("Only owner of the display can reparent surfaces to it.");
- }
-
- synchronized (mGlobalLock) {
- long token = Binder.clearCallingIdentity();
- try {
- DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
- displayContent.reparentDisplayContent(sc);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- }
-
- @Override
public boolean injectInputAfterTransactionsApplied(InputEvent ev, int mode) {
boolean shouldWaitForAnimToComplete = false;
if (ev instanceof KeyEvent) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8123182..5ef184a 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1078,7 +1078,8 @@
+ mRequestedWidth + ", mRequestedheight="
+ mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
+ "): frame=" + mWindowFrames.mFrame.toShortString()
- + " " + mWindowFrames.getInsetsInfo());
+ + " " + mWindowFrames.getInsetsInfo()
+ + " " + mAttrs.getTitle());
}
// TODO: Look into whether this override is still necessary.
@@ -1312,6 +1313,7 @@
mOrientationChangeTimedOut = true;
}
+ @Override
DisplayContent getDisplayContent() {
return mToken.getDisplayContent();
}
@@ -3142,7 +3144,8 @@
}
//TODO (multidisplay): Accessibility supported only for the default display.
- if (mWmService.mAccessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
+ if (mWmService.mAccessibilityController != null && (getDisplayId() == DEFAULT_DISPLAY
+ || getDisplayContent().getParentWindow() != null)) {
mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
}
@@ -4207,7 +4210,8 @@
}
//TODO (multidisplay): Accessibility is supported only for the default display.
- if (mWmService.mAccessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
+ if (mWmService.mAccessibilityController != null && (getDisplayId() == DEFAULT_DISPLAY
+ || getDisplayContent().getParentWindow() != null)) {
mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
}
@@ -4597,9 +4601,9 @@
anim.scaleCurrentDuration(mWmService.getWindowAnimationScaleLocked());
final AnimationAdapter adapter = new LocalAnimationAdapter(
new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */,
- mToken.getWindowCornerRadiusForAnimation()),
+ 0 /* windowCornerRadius */),
mWmService.mSurfaceAnimationRunner);
- startAnimation(mPendingTransaction, adapter);
+ startAnimation(getPendingTransaction(), adapter);
commitPendingTransaction();
}
@@ -4646,6 +4650,18 @@
int x = mSurfacePosition.x;
int y = mSurfacePosition.y;
+ // We might be on a display which has been re-parented to a view in another window, so here
+ // computes the global location of our display.
+ DisplayContent dc = getDisplayContent();
+ while (dc != null && dc.getParentWindow() != null) {
+ final WindowState displayParent = dc.getParentWindow();
+ x += displayParent.mWindowFrames.mFrame.left - displayParent.mAttrs.surfaceInsets.left
+ + (dc.getLocationInParentWindow().x * displayParent.mGlobalScale + 0.5f);
+ y += displayParent.mWindowFrames.mFrame.top - displayParent.mAttrs.surfaceInsets.top
+ + (dc.getLocationInParentWindow().y * displayParent.mGlobalScale + 0.5f);
+ dc = displayParent.getDisplayContent();
+ }
+
// If changed, also adjust transformFrameToSurfacePosition
final WindowContainer parent = getParent();
if (isChildWindow()) {
@@ -4795,8 +4811,8 @@
}
@Override
- public void onAnimationLeashDestroyed(Transaction t) {
- super.onAnimationLeashDestroyed(t);
+ public void onAnimationLeashLost(Transaction t) {
+ super.onAnimationLeashLost(t);
updateSurfacePosition(t);
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 20e1ac6..10a63ee 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -766,7 +766,7 @@
return false;
}
- if (w.inPinnedWindowingMode()) {
+ if (w.getWindowConfiguration().tasksAreFloating()) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index f65f0ab..8aee0f2 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -82,9 +82,6 @@
// windows will be put to the bottom of the list.
boolean sendingToBottom;
- // The display this token is on.
- protected DisplayContent mDisplayContent;
-
/** The owner has {@link android.Manifest.permission#MANAGE_APP_TOKENS} */
final boolean mOwnerCanManageAppTokens;
@@ -249,10 +246,6 @@
return null;
}
- DisplayContent getDisplayContent() {
- return mDisplayContent;
- }
-
@Override
void removeImmediately() {
if (mDisplayContent != null) {
@@ -266,7 +259,6 @@
@Override
void onDisplayChanged(DisplayContent dc) {
dc.reParentWindowToken(this);
- mDisplayContent = dc;
// TODO(b/36740756): One day this should perhaps be hooked
// up with goodToGo, so we don't move a window
@@ -345,8 +337,4 @@
mOwnerCanManageAppTokens);
return mOwnerCanManageAppTokens && (layer > navLayer);
}
-
- float getWindowCornerRadiusForAnimation() {
- return mDisplayContent.isDefaultDisplay ? mWmService.mWindowCornerRadius : 0;
- }
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 204a1ea..fb3076b 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -59,6 +59,7 @@
#include <android_view_PointerIcon.h>
#include <android/graphics/GraphicsJNI.h>
+#include <nativehelper/ScopedLocalFrame.h>
#include <nativehelper/ScopedLocalRef.h>
#include <nativehelper/ScopedPrimitiveArray.h>
#include <nativehelper/ScopedUtfChars.h>
@@ -723,6 +724,7 @@
ATRACE_CALL();
JNIEnv* env = jniEnv();
+ ScopedLocalFrame localFrame(env);
jobject tokenObj = javaObjectForIBinder(env, token);
jstring reasonObj = env->NewStringUTF(reason.c_str());
@@ -735,8 +737,6 @@
} else {
assert(newTimeout >= 0);
}
-
- env->DeleteLocalRef(reasonObj);
return newTimeout;
}
@@ -747,6 +747,7 @@
ATRACE_CALL();
JNIEnv* env = jniEnv();
+ ScopedLocalFrame localFrame(env);
jobject tokenObj = javaObjectForIBinder(env, token);
if (tokenObj) {
@@ -764,6 +765,7 @@
ATRACE_CALL();
JNIEnv* env = jniEnv();
+ ScopedLocalFrame localFrame(env);
jobject oldTokenObj = javaObjectForIBinder(env, oldToken);
jobject newTokenObj = javaObjectForIBinder(env, newToken);
@@ -1139,6 +1141,7 @@
nsecs_t result = 0;
if (policyFlags & POLICY_FLAG_TRUSTED) {
JNIEnv* env = jniEnv();
+ ScopedLocalFrame localFrame(env);
// Token may be null
jobject tokenObj = javaObjectForIBinder(env, token);
@@ -1173,6 +1176,7 @@
bool result = false;
if (policyFlags & POLICY_FLAG_TRUSTED) {
JNIEnv* env = jniEnv();
+ ScopedLocalFrame localFrame(env);
// Note: tokenObj may be null.
jobject tokenObj = javaObjectForIBinder(env, token);
@@ -1224,6 +1228,7 @@
void NativeInputManager::onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
+ ScopedLocalFrame localFrame(env);
jobject touchedTokenObj = javaObjectForIBinder(env, touchedToken);
env->CallVoidMethod(mServiceObj, gServiceClassInfo.onPointerDownOutsideFocus, touchedTokenObj);
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 4d37f1a..da17579 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -45,6 +45,13 @@
#include <string.h>
#include <utils/SystemClock.h>
+static jclass class_gnssMeasurementsEvent;
+static jclass class_gnssMeasurement;
+static jclass class_location;
+static jclass class_gnssNavigationMessage;
+static jclass class_gnssClock;
+static jclass class_gnssConfiguration_halInterfaceVersion;
+
static jobject mCallbacksObj = nullptr;
static jmethodID method_reportLocation;
@@ -55,7 +62,7 @@
static jmethodID method_setTopHalCapabilities;
static jmethodID method_setGnssYearOfHardware;
static jmethodID method_setGnssHardwareModelName;
-static jmethodID method_xtraDownloadRequest;
+static jmethodID method_psdsDownloadRequest;
static jmethodID method_reportNiNotification;
static jmethodID method_requestLocation;
static jmethodID method_requestRefLocation;
@@ -95,6 +102,12 @@
static jmethodID method_correctionPlaneAzimDeg;
static jmethodID method_reportNfwNotification;
static jmethodID method_isInEmergencySession;
+static jmethodID method_gnssMeasurementsEventCtor;
+static jmethodID method_locationCtor;
+static jmethodID method_gnssNavigationMessageCtor;
+static jmethodID method_gnssClockCtor;
+static jmethodID method_gnssMeasurementCtor;
+static jmethodID method_halInterfaceVersionCtor;
/*
* Save a pointer to JavaVm to attach/detach threads executing
@@ -255,11 +268,11 @@
class JavaObject {
public:
- JavaObject(JNIEnv* env, const char* class_name);
- JavaObject(JNIEnv* env, const char* class_name, const char * sz_arg_1);
- JavaObject(JNIEnv* env, const char* class_name, jobject object);
+ JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor);
+ JavaObject(JNIEnv* env, jclass clazz, jmethodID stringCtor, const char * sz_arg_1);
+ JavaObject(JNIEnv* env, jclass clazz, jobject object);
- virtual ~JavaObject();
+ virtual ~JavaObject() = default;
template<class T>
void callSetter(const char* method_name, T value);
@@ -273,25 +286,20 @@
jobject object_;
};
-JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
- clazz_ = env_->FindClass(class_name);
- jmethodID ctor = env->GetMethodID(clazz_, "<init>", "()V");
- object_ = env_->NewObject(clazz_, ctor);
+JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor) : env_(env),
+ clazz_(clazz) {
+ object_ = env_->NewObject(clazz_, defaultCtor);
}
-JavaObject::JavaObject(JNIEnv* env, const char* class_name, const char * sz_arg_1) : env_(env) {
- clazz_ = env_->FindClass(class_name);
- jmethodID ctor = env->GetMethodID(clazz_, "<init>", "(Ljava/lang/String;)V");
- object_ = env_->NewObject(clazz_, ctor, env->NewStringUTF(sz_arg_1));
+
+JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID stringCtor, const char * sz_arg_1)
+ : env_(env), clazz_(clazz) {
+ object_ = env_->NewObject(clazz_, stringCtor, env->NewStringUTF(sz_arg_1));
}
-JavaObject::JavaObject(JNIEnv* env, const char* class_name, jobject object)
- : env_(env), object_(object) {
- clazz_ = env_->FindClass(class_name);
-}
-JavaObject::~JavaObject() {
- env_->DeleteLocalRef(clazz_);
+JavaObject::JavaObject(JNIEnv* env, jclass clazz, jobject object)
+ : env_(env), clazz_(clazz), object_(object) {
}
template<class T>
@@ -358,11 +366,8 @@
}
static jobject createHalInterfaceVersionJavaObject(JNIEnv* env, jint major, jint minor) {
- jclass versionClass =
- env->FindClass("com/android/server/location/GnssConfiguration$HalInterfaceVersion");
- jmethodID versionCtor = env->GetMethodID(versionClass, "<init>", "(II)V");
- jobject version = env->NewObject(versionClass, versionCtor, major, minor);
- env->DeleteLocalRef(versionClass);
+ jobject version = env->NewObject(class_gnssConfiguration_halInterfaceVersion,
+ method_halInterfaceVersionCtor, major, minor);
return version;
}
@@ -452,7 +457,7 @@
static jobject translateGnssLocation(JNIEnv* env,
const GnssLocation_V1_0& location) {
- JavaObject object(env, "android/location/Location", "gps");
+ JavaObject object(env, class_location, method_locationCtor, "gps");
uint16_t flags = static_cast<uint32_t>(location.gnssLocationFlags);
if (flags & GnssLocationFlags::HAS_LAT_LONG) {
@@ -488,8 +493,7 @@
static jobject translateGnssLocation(JNIEnv* env,
const GnssLocation_V2_0& location) {
- JavaObject object(env, "android/location/Location",
- translateGnssLocation(env, location.v1_0));
+ JavaObject object(env, class_location, translateGnssLocation(env, location.v1_0));
const uint16_t flags = static_cast<uint16_t>(location.elapsedRealtime.flags);
@@ -798,7 +802,7 @@
*/
Return<void> GnssXtraCallback::downloadRequestCb() {
JNIEnv* env = getJniEnv();
- env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
+ env->CallVoidMethod(mCallbacksObj, method_psdsDownloadRequest);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return Void();
}
@@ -946,7 +950,7 @@
return Void();
}
- JavaObject object(env, "android/location/GnssNavigationMessage");
+ JavaObject object(env, class_gnssNavigationMessage, method_gnssNavigationMessageCtor);
SET(Type, static_cast<int32_t>(message.type));
SET(Svid, static_cast<int32_t>(message.svid));
SET(MessageId, static_cast<int32_t>(message.messageId));
@@ -1013,7 +1017,7 @@
void GnssMeasurementCallback::translateAndSetGnssData(const T& data) {
JNIEnv* env = getJniEnv();
- JavaObject gnssClockJavaObject(env, "android/location/GnssClock");
+ JavaObject gnssClockJavaObject(env, class_gnssClock, method_gnssClockCtor);
translateGnssClock(gnssClockJavaObject, data);
jobject clock = gnssClockJavaObject.get();
@@ -1175,41 +1179,30 @@
return nullptr;
}
- jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
jobjectArray gnssMeasurementArray = env->NewObjectArray(
count,
- gnssMeasurementClass,
+ class_gnssMeasurement,
nullptr /* initialElement */);
for (uint16_t i = 0; i < count; ++i) {
- JavaObject object(env, "android/location/GnssMeasurement");
+ JavaObject object(env, class_gnssMeasurement, method_gnssMeasurementCtor);
translateSingleGnssMeasurement(&(measurements[i]), object);
env->SetObjectArrayElement(gnssMeasurementArray, i, object.get());
}
- env->DeleteLocalRef(gnssMeasurementClass);
return gnssMeasurementArray;
}
void GnssMeasurementCallback::setMeasurementData(JNIEnv* env, jobject clock,
jobjectArray measurementArray) {
- jclass gnssMeasurementsEventClass =
- env->FindClass("android/location/GnssMeasurementsEvent");
- jmethodID gnssMeasurementsEventCtor =
- env->GetMethodID(
- gnssMeasurementsEventClass,
- "<init>",
- "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
-
- jobject gnssMeasurementsEvent = env->NewObject(gnssMeasurementsEventClass,
- gnssMeasurementsEventCtor,
+ jobject gnssMeasurementsEvent = env->NewObject(class_gnssMeasurementsEvent,
+ method_gnssMeasurementsEventCtor,
clock,
measurementArray);
env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData,
gnssMeasurementsEvent);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
- env->DeleteLocalRef(gnssMeasurementsEventClass);
env->DeleteLocalRef(gnssMeasurementsEvent);
}
@@ -1464,8 +1457,7 @@
Return<void> GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(const hidl_vec<T>& locations) {
JNIEnv* env = getJniEnv();
- jobjectArray jLocations = env->NewObjectArray(locations.size(),
- env->FindClass("android/location/Location"), nullptr);
+ jobjectArray jLocations = env->NewObjectArray(locations.size(), class_location, nullptr);
for (uint16_t i = 0; i < locations.size(); ++i) {
jobject jLocation = translateGnssLocation(env, locations[i]);
@@ -1503,7 +1495,8 @@
}
};
-static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
+/* Initializes the GNSS service handle. */
+static void android_location_GnssLocationProvider_set_gps_service_handle() {
gnssHal_V2_0 = IGnss_V2_0::getService();
if (gnssHal_V2_0 != nullptr) {
gnssHal = gnssHal_V2_0;
@@ -1522,7 +1515,12 @@
gnssHal = IGnss_V1_0::getService();
}
-static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass clazz) {
+/* One time initialization at system boot */
+static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
+ // Initialize the top level gnss HAL handle.
+ android_location_GnssLocationProvider_set_gps_service_handle();
+
+ // Cache methodIDs and class IDs.
method_reportLocation = env->GetMethodID(clazz, "reportLocation",
"(ZLandroid/location/Location;)V");
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
@@ -1533,7 +1531,7 @@
method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
method_setGnssHardwareModelName = env->GetMethodID(clazz, "setGnssHardwareModelName",
"(Ljava/lang/String;)V");
- method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
+ method_psdsDownloadRequest = env->GetMethodID(clazz, "psdsDownloadRequest", "()V");
method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
"(IIIIILjava/lang/String;Ljava/lang/String;II)V");
method_requestLocation = env->GetMethodID(clazz, "requestLocation", "(ZZ)V");
@@ -1617,6 +1615,40 @@
method_correctionPlaneAltDeg = env->GetMethodID(refPlaneClass, "getAltitudeMeters", "()D");
method_correctionPlaneAzimDeg = env->GetMethodID(refPlaneClass, "getAzimuthDegrees", "()D");
+ jclass gnssMeasurementsEventClass = env->FindClass("android/location/GnssMeasurementsEvent");
+ class_gnssMeasurementsEvent= (jclass) env->NewGlobalRef(gnssMeasurementsEventClass);
+ method_gnssMeasurementsEventCtor = env->GetMethodID(
+ class_gnssMeasurementsEvent,
+ "<init>",
+ "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
+
+ jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
+ class_gnssMeasurement = (jclass) env->NewGlobalRef(gnssMeasurementClass);
+ method_gnssMeasurementCtor = env->GetMethodID(class_gnssMeasurement, "<init>", "()V");
+
+ jclass locationClass = env->FindClass("android/location/Location");
+ class_location = (jclass) env->NewGlobalRef(locationClass);
+ method_locationCtor = env->GetMethodID(class_location, "<init>", "(Ljava/lang/String;)V");
+
+ jclass gnssNavigationMessageClass = env->FindClass("android/location/GnssNavigationMessage");
+ class_gnssNavigationMessage = (jclass) env->NewGlobalRef(gnssNavigationMessageClass);
+ method_gnssNavigationMessageCtor = env->GetMethodID(class_gnssNavigationMessage, "<init>", "()V");
+
+ jclass gnssClockClass = env->FindClass("android/location/GnssClock");
+ class_gnssClock = (jclass) env->NewGlobalRef(gnssClockClass);
+ method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V");
+
+ jclass gnssConfiguration_halInterfaceVersionClass =
+ env->FindClass("com/android/server/location/GnssConfiguration$HalInterfaceVersion");
+ class_gnssConfiguration_halInterfaceVersion =
+ (jclass) env->NewGlobalRef(gnssConfiguration_halInterfaceVersionClass);
+ method_halInterfaceVersionCtor =
+ env->GetMethodID(class_gnssConfiguration_halInterfaceVersion, "<init>", "(II)V");
+}
+
+/* Initialization needed at system boot and whenever GNSS service dies. */
+static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass clazz,
+ jboolean reinitializeGnssServiceHandle) {
/*
* Save a pointer to JVM.
*/
@@ -1625,6 +1657,10 @@
LOG_ALWAYS_FATAL("Unable to get Java VM. Error: %d", jvmStatus);
}
+ if (reinitializeGnssServiceHandle) {
+ android_location_GnssLocationProvider_set_gps_service_handle();
+ }
+
if (gnssHal == nullptr) {
ALOGE("Unable to get GPS service\n");
return;
@@ -1849,6 +1885,7 @@
return createHalInterfaceVersionJavaObject(env, major, minor);
}
+/* Initialization needed each time the GPS service is shutdown. */
static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj) {
/*
* This must be set before calling into the HAL library.
@@ -2168,12 +2205,12 @@
}
}
-static jboolean android_location_GnssLocationProvider_supports_xtra(
+static jboolean android_location_GnssLocationProvider_supports_psds(
JNIEnv* /* env */, jobject /* obj */) {
return (gnssXtraIface != nullptr) ? JNI_TRUE : JNI_FALSE;
}
-static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
+static void android_location_GnssLocationProvider_inject_psds_data(JNIEnv* env, jobject /* obj */,
jbyteArray data, jint length) {
if (gnssXtraIface == nullptr) {
ALOGE("XTRA Interface not supported");
@@ -3004,7 +3041,7 @@
android_location_GnssLocationProvider_class_init_native)},
{"native_is_supported", "()Z", reinterpret_cast<void *>(
android_location_GnssLocationProvider_is_supported)},
- {"native_init_once", "()V", reinterpret_cast<void *>(
+ {"native_init_once", "(Z)V", reinterpret_cast<void *>(
android_location_GnssLocationProvider_init_once)},
{"native_init", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_init)},
{"native_cleanup", "()V", reinterpret_cast<void *>(
@@ -3025,10 +3062,10 @@
android_location_GnssLocationProvider_inject_best_location)},
{"native_inject_location", "(DDF)V", reinterpret_cast<void *>(
android_location_GnssLocationProvider_inject_location)},
- {"native_supports_xtra", "()Z", reinterpret_cast<void *>(
- android_location_GnssLocationProvider_supports_xtra)},
- {"native_inject_xtra_data", "([BI)V", reinterpret_cast<void *>(
- android_location_GnssLocationProvider_inject_xtra_data)},
+ {"native_supports_psds", "()Z", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_supports_psds)},
+ {"native_inject_psds_data", "([BI)V", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_inject_psds_data)},
{"native_agps_set_id", "(ILjava/lang/String;)V", reinterpret_cast<void *>(
android_location_GnssLocationProvider_agps_set_id)},
{"native_agps_set_ref_location_cellid", "(IIIII)V", reinterpret_cast<void *>(
diff --git a/services/core/xsd/vts/Android.bp b/services/core/xsd/vts/Android.bp
index 967750d..5545656 100644
--- a/services/core/xsd/vts/Android.bp
+++ b/services/core/xsd/vts/Android.bp
@@ -25,6 +25,7 @@
],
shared_libs: [
"liblog",
+ "libbase",
],
cflags: [
"-Wall",
diff --git a/services/core/xsd/vts/ValidateDefaultPermissions.cpp b/services/core/xsd/vts/ValidateDefaultPermissions.cpp
index 54c115b..518f7bb 100644
--- a/services/core/xsd/vts/ValidateDefaultPermissions.cpp
+++ b/services/core/xsd/vts/ValidateDefaultPermissions.cpp
@@ -16,13 +16,48 @@
#include "utility/ValidateXml.h"
-TEST(CheckConfig, mediaDefaultPermissions) {
+#include <dirent.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <string>
+
+#include <android-base/strings.h>
+
+static std::vector<std::string> get_files_in_dirs(const char* dir_path) {
+ std::vector<std::string> files;
+ std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dir_path), closedir);
+
+ if (d == nullptr) {
+ return files;
+ }
+
+ struct dirent* de;
+ while ((de = readdir(d.get()))) {
+ if (de->d_type != DT_REG) {
+ continue;
+ }
+ if (android::base::EndsWith(de->d_name, ".xml")) {
+ files.push_back(de->d_name);
+ }
+ }
+ return files;
+}
+
+TEST(CheckConfig, defaultPermissions) {
RecordProperty("description",
"Verify that the default-permissions file "
"is valid according to the schema");
- const char* location = "/vendor/etc/default-permissions";
+ std::vector<const char*> locations = {"/vendor/etc/default-permissions",
+ "/odm/etc/default-permissions"};
- EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS("default-permissions.xml", {location},
- "/data/local/tmp/default-permissions.xsd");
+ for (const char* dir_path : locations) {
+ std::vector<std::string> files = get_files_in_dirs(dir_path);
+ for (auto& file_name : files) {
+ EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(file_name.c_str(), {dir_path},
+ "/data/local/tmp/default-permissions.xsd");
+ }
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index c5a2068..22231c0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8034,6 +8034,7 @@
throw new IllegalArgumentException("Component " + who
+ " not installed for userId:" + userHandle);
}
+
final boolean hasIncompatibleAccountsOrNonAdb =
hasIncompatibleAccountsOrNonAdbNoLock(userHandle, who);
synchronized (getLockObject()) {
@@ -8539,9 +8540,30 @@
return;
}
enforceCanManageProfileAndDeviceOwners();
- if ((mIsWatch || hasUserSetupCompleted(userHandle)) && !isCallerWithSystemUid()) {
- throw new IllegalStateException("Cannot set the profile owner on a user which is "
- + "already set-up");
+
+ if ((mIsWatch || hasUserSetupCompleted(userHandle))) {
+ if (!isCallerWithSystemUid()) {
+ throw new IllegalStateException("Cannot set the profile owner on a user which is "
+ + "already set-up");
+ }
+
+ if (!mIsWatch) {
+ // Only the default supervision profile owner can be set as profile owner after SUW
+ final String supervisor = mContext.getResources().getString(
+ com.android.internal.R.string
+ .config_defaultSupervisionProfileOwnerComponent);
+ if (supervisor == null) {
+ throw new IllegalStateException("Unable to set profile owner post-setup, no"
+ + "default supervisor profile owner defined");
+ }
+
+ final ComponentName supervisorComponent = ComponentName.unflattenFromString(
+ supervisor);
+ if (!owner.equals(supervisorComponent)) {
+ throw new IllegalStateException("Unable to set non-default profile owner"
+ + " post-setup " + owner);
+ }
+ }
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
index 344077c..0838fbc 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
@@ -20,7 +20,6 @@
import android.app.Notification;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
@@ -65,7 +64,7 @@
dialogIntent, 0, null, UserHandle.CURRENT);
Notification.Builder builder =
- new Notification.Builder(context, SystemNotificationChannels.DEVELOPER)
+ new Notification.Builder(context, SystemNotificationChannels.DEVICE_ADMIN)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
.setOngoing(true)
.setLocalOnly(true)
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 4ac8342..2b5cd01 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -115,7 +115,6 @@
import com.android.server.os.BugreportManagerService;
import com.android.server.os.DeviceIdentifiersPolicyService;
import com.android.server.os.SchedulingPolicyService;
-import com.android.server.pm.ApexManager;
import com.android.server.pm.BackgroundDexOptService;
import com.android.server.pm.CrossProfileAppsService;
import com.android.server.pm.DynamicCodeLoggingService;
@@ -628,12 +627,6 @@
watchdog.start();
traceEnd();
- // Start ApexManager as early as we can to give it enough time to call apexd and populate
- // cache of known apex packages. Note that calling apexd will happen asynchronously.
- traceBeginAndSlog("StartApexManager");
- mSystemServiceManager.startService(ApexManager.class);
- traceEnd();
-
Slog.i(TAG, "Reading configuration...");
final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";
traceBeginAndSlog(TAG_SYSTEM_CONFIG);
@@ -1174,9 +1167,12 @@
if (!mOnlyCore) {
traceBeginAndSlog("UpdatePackagesIfNeeded");
try {
+ Watchdog.getInstance().pauseWatchingCurrentThread("dexopt");
mPackageManagerService.updatePackagesIfNeeded();
} catch (Throwable e) {
reportWtf("update packages", e);
+ } finally {
+ Watchdog.getInstance().resumeWatchingCurrentThread("dexopt");
}
traceEnd();
}
@@ -1206,12 +1202,12 @@
traceBeginAndSlog("StartPersistentDataBlock");
mSystemServiceManager.startService(PersistentDataBlockService.class);
traceEnd();
-
- traceBeginAndSlog("StartTestHarnessMode");
- mSystemServiceManager.startService(TestHarnessModeService.class);
- traceEnd();
}
+ traceBeginAndSlog("StartTestHarnessMode");
+ mSystemServiceManager.startService(TestHarnessModeService.class);
+ traceEnd();
+
if (hasPdb || OemLockService.isHalPresent()) {
// Implementation depends on pdb or the OemLock HAL
traceBeginAndSlog("StartOemLockService");
@@ -1407,6 +1403,7 @@
traceBeginAndSlog("StartNotificationManager");
mSystemServiceManager.startService(NotificationManagerService.class);
+ SystemNotificationChannels.removeDeprecated(context);
SystemNotificationChannels.createAll(context);
notification = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
diff --git a/services/net/java/android/net/IpMemoryStore.java b/services/net/java/android/net/IpMemoryStore.java
index 4a115e6..6f91e00 100644
--- a/services/net/java/android/net/IpMemoryStore.java
+++ b/services/net/java/android/net/IpMemoryStore.java
@@ -18,11 +18,14 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
/**
* Manager class used to communicate with the ip memory store service in the network stack,
@@ -30,15 +33,18 @@
* @hide
*/
public class IpMemoryStore extends IpMemoryStoreClient {
- private final CompletableFuture<IIpMemoryStore> mService;
+ private static final String TAG = IpMemoryStore.class.getSimpleName();
+ @NonNull private final CompletableFuture<IIpMemoryStore> mService;
+ @NonNull private final AtomicReference<CompletableFuture<IIpMemoryStore>> mTailNode;
public IpMemoryStore(@NonNull final Context context) {
super(context);
mService = new CompletableFuture<>();
+ mTailNode = new AtomicReference<CompletableFuture<IIpMemoryStore>>(mService);
getNetworkStackClient().fetchIpMemoryStore(
new IIpMemoryStoreCallbacks.Stub() {
@Override
- public void onIpMemoryStoreFetched(final IIpMemoryStore memoryStore) {
+ public void onIpMemoryStoreFetched(@NonNull final IIpMemoryStore memoryStore) {
mService.complete(memoryStore);
}
@@ -49,9 +55,28 @@
});
}
+ /*
+ * If the IpMemoryStore is ready, this function will run the request synchronously.
+ * Otherwise, it will enqueue the requests for execution immediately after the
+ * service becomes ready. The requests are guaranteed to be executed in the order
+ * they are sumbitted.
+ */
@Override
- protected IIpMemoryStore getService() throws InterruptedException, ExecutionException {
- return mService.get();
+ protected void runWhenServiceReady(Consumer<IIpMemoryStore> cb) throws ExecutionException {
+ mTailNode.getAndUpdate(future -> future.handle((store, exception) -> {
+ if (exception != null) {
+ // this should never happens since we also catch the exception below
+ Log.wtf(TAG, "Error fetching IpMemoryStore", exception);
+ return store;
+ }
+
+ try {
+ cb.accept(store);
+ } catch (Exception e) {
+ Log.wtf(TAG, "Exception occured: " + e.getMessage());
+ }
+ return store;
+ }));
}
@VisibleForTesting
diff --git a/services/net/java/android/net/IpMemoryStoreClient.java b/services/net/java/android/net/IpMemoryStoreClient.java
index 379c017..3d56202 100644
--- a/services/net/java/android/net/IpMemoryStoreClient.java
+++ b/services/net/java/android/net/IpMemoryStoreClient.java
@@ -31,6 +31,7 @@
import android.util.Log;
import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
/**
* service used to communicate with the ip memory store service in network stack,
@@ -46,8 +47,25 @@
mContext = context;
}
- @NonNull
- protected abstract IIpMemoryStore getService() throws InterruptedException, ExecutionException;
+ protected abstract void runWhenServiceReady(Consumer<IIpMemoryStore> cb)
+ throws ExecutionException;
+
+ @FunctionalInterface
+ private interface ThrowingRunnable {
+ void run() throws RemoteException;
+ }
+
+ private void ignoringRemoteException(ThrowingRunnable r) {
+ ignoringRemoteException("Failed to execute remote procedure call", r);
+ }
+
+ private void ignoringRemoteException(String message, ThrowingRunnable r) {
+ try {
+ r.run();
+ } catch (RemoteException e) {
+ Log.e(TAG, message, e);
+ }
+ }
/**
* Store network attributes for a given L2 key.
@@ -69,14 +87,12 @@
@NonNull final NetworkAttributes attributes,
@Nullable final OnStatusListener listener) {
try {
- try {
- getService().storeNetworkAttributes(l2Key, attributes.toParcelable(),
- OnStatusListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onComplete(new Status(Status.ERROR_UNKNOWN));
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error storing network attributes", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.storeNetworkAttributes(l2Key, attributes.toParcelable(),
+ OnStatusListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error storing network attributes",
+ () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN)));
}
}
@@ -95,14 +111,12 @@
@NonNull final String name, @NonNull final Blob data,
@Nullable final OnStatusListener listener) {
try {
- try {
- getService().storeBlob(l2Key, clientId, name, data,
- OnStatusListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onComplete(new Status(Status.ERROR_UNKNOWN));
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error storing blob", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.storeBlob(l2Key, clientId, name, data,
+ OnStatusListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error storing blob",
+ () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN)));
}
}
@@ -123,14 +137,12 @@
public void findL2Key(@NonNull final NetworkAttributes attributes,
@NonNull final OnL2KeyResponseListener listener) {
try {
- try {
- getService().findL2Key(attributes.toParcelable(),
- OnL2KeyResponseListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onL2KeyResponse(new Status(Status.ERROR_UNKNOWN), null);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error finding L2 Key", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.findL2Key(attributes.toParcelable(),
+ OnL2KeyResponseListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error finding L2 Key",
+ () -> listener.onL2KeyResponse(new Status(Status.ERROR_UNKNOWN), null));
}
}
@@ -146,14 +158,12 @@
public void isSameNetwork(@NonNull final String l2Key1, @NonNull final String l2Key2,
@NonNull final OnSameL3NetworkResponseListener listener) {
try {
- try {
- getService().isSameNetwork(l2Key1, l2Key2,
- OnSameL3NetworkResponseListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onSameL3NetworkResponse(new Status(Status.ERROR_UNKNOWN), null);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error checking for network sameness", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.isSameNetwork(l2Key1, l2Key2,
+ OnSameL3NetworkResponseListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error checking for network sameness",
+ () -> listener.onSameL3NetworkResponse(new Status(Status.ERROR_UNKNOWN), null));
}
}
@@ -169,14 +179,13 @@
public void retrieveNetworkAttributes(@NonNull final String l2Key,
@NonNull final OnNetworkAttributesRetrievedListener listener) {
try {
- try {
- getService().retrieveNetworkAttributes(l2Key,
- OnNetworkAttributesRetrievedListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onNetworkAttributesRetrieved(new Status(Status.ERROR_UNKNOWN), null, null);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error retrieving network attributes", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.retrieveNetworkAttributes(l2Key,
+ OnNetworkAttributesRetrievedListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error retrieving network attributes",
+ () -> listener.onNetworkAttributesRetrieved(new Status(Status.ERROR_UNKNOWN),
+ null, null));
}
}
@@ -194,14 +203,13 @@
public void retrieveBlob(@NonNull final String l2Key, @NonNull final String clientId,
@NonNull final String name, @NonNull final OnBlobRetrievedListener listener) {
try {
- try {
- getService().retrieveBlob(l2Key, clientId, name,
- OnBlobRetrievedListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onBlobRetrieved(new Status(Status.ERROR_UNKNOWN), null, null, null);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error retrieving blob", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.retrieveBlob(l2Key, clientId, name,
+ OnBlobRetrievedListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error retrieving blob",
+ () -> listener.onBlobRetrieved(new Status(Status.ERROR_UNKNOWN),
+ null, null, null));
}
}
}
diff --git a/services/net/java/android/net/ip/IpClientManager.java b/services/net/java/android/net/ip/IpClientManager.java
new file mode 100644
index 0000000..f8d7e84
--- /dev/null
+++ b/services/net/java/android/net/ip/IpClientManager.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.ip;
+
+import android.annotation.NonNull;
+import android.net.NattKeepalivePacketData;
+import android.net.ProxyInfo;
+import android.net.TcpKeepalivePacketData;
+import android.net.shared.ProvisioningConfiguration;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A convenience wrapper for IpClient.
+ *
+ * Wraps IIpClient calls, making them a bit more friendly to use. Currently handles:
+ * - Clearing calling identity
+ * - Ignoring RemoteExceptions
+ * - Converting to stable parcelables
+ *
+ * By design, all methods on IIpClient are asynchronous oneway IPCs and are thus void. All the
+ * wrapper methods in this class return a boolean that callers can use to determine whether
+ * RemoteException was thrown.
+ */
+public class IpClientManager {
+ @NonNull private final IIpClient mIpClient;
+ @NonNull private final String mTag;
+
+ public IpClientManager(@NonNull IIpClient ipClient, @NonNull String tag) {
+ mIpClient = ipClient;
+ mTag = tag;
+ }
+
+ public IpClientManager(@NonNull IIpClient ipClient) {
+ this(ipClient, IpClientManager.class.getSimpleName());
+ }
+
+ private void log(String s, Throwable e) {
+ Log.e(mTag, s, e);
+ }
+
+ /**
+ * For clients using {@link ProvisioningConfiguration.Builder#withPreDhcpAction()}, must be
+ * called after {@link IIpClientCallbacks#onPreDhcpAction} to indicate that DHCP is clear to
+ * proceed.
+ */
+ public boolean completedPreDhcpAction() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.completedPreDhcpAction();
+ return true;
+ } catch (RemoteException e) {
+ log("Error completing PreDhcpAction", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Confirm the provisioning configuration.
+ */
+ public boolean confirmConfiguration() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.confirmConfiguration();
+ return true;
+ } catch (RemoteException e) {
+ log("Error confirming IpClient configuration", e);
+ return false;
+ }
+ }
+
+ /**
+ * Indicate that packet filter read is complete.
+ */
+ public boolean readPacketFilterComplete(byte[] data) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.readPacketFilterComplete(data);
+ return true;
+ } catch (RemoteException e) {
+ log("Error notifying IpClient of packet filter read", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Shut down this IpClient instance altogether.
+ */
+ public boolean shutdown() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.shutdown();
+ return true;
+ } catch (RemoteException e) {
+ log("Error shutting down IpClient", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Start provisioning with the provided parameters.
+ */
+ public boolean startProvisioning(ProvisioningConfiguration prov) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.startProvisioning(prov.toStableParcelable());
+ return true;
+ } catch (RemoteException e) {
+ log("Error starting IpClient provisioning", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Stop this IpClient.
+ *
+ * <p>This does not shut down the StateMachine itself, which is handled by {@link #shutdown()}.
+ */
+ public boolean stop() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.stop();
+ return true;
+ } catch (RemoteException e) {
+ log("Error stopping IpClient", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the TCP buffer sizes to use.
+ *
+ * This may be called, repeatedly, at any time before or after a call to
+ * #startProvisioning(). The setting is cleared upon calling #stop().
+ */
+ public boolean setTcpBufferSizes(String tcpBufferSizes) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setTcpBufferSizes(tcpBufferSizes);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting IpClient TCP buffer sizes", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the HTTP Proxy configuration to use.
+ *
+ * This may be called, repeatedly, at any time before or after a call to
+ * #startProvisioning(). The setting is cleared upon calling #stop().
+ */
+ public boolean setHttpProxy(ProxyInfo proxyInfo) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setHttpProxy(proxyInfo);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting IpClient proxy", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Enable or disable the multicast filter. Attempts to use APF to accomplish the filtering,
+ * if not, Callback.setFallbackMulticastFilter() is called.
+ */
+ public boolean setMulticastFilter(boolean enabled) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setMulticastFilter(enabled);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting multicast filter", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Add a TCP keepalive packet filter before setting up keepalive offload.
+ */
+ public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketData pkt) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.addKeepalivePacketFilter(slot, pkt.toStableParcelable());
+ return true;
+ } catch (RemoteException e) {
+ log("Error adding Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Add a NAT-T keepalive packet filter before setting up keepalive offload.
+ */
+ public boolean addKeepalivePacketFilter(int slot, NattKeepalivePacketData pkt) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.addNattKeepalivePacketFilter(slot, pkt.toStableParcelable());
+ return true;
+ } catch (RemoteException e) {
+ log("Error adding Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Remove a keepalive packet filter after stopping keepalive offload.
+ */
+ public boolean removeKeepalivePacketFilter(int slot) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.removeKeepalivePacketFilter(slot);
+ return true;
+ } catch (RemoteException e) {
+ log("Error removing Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the L2 key and group hint for storing info into the memory store.
+ */
+ public boolean setL2KeyAndGroupHint(String l2Key, String groupHint) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setL2KeyAndGroupHint(l2Key, groupHint);
+ return true;
+ } catch (RemoteException e) {
+ log("Failed setL2KeyAndGroupHint", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+}
diff --git a/services/net/java/android/net/shared/NetworkMonitorUtils.java b/services/net/java/android/net/shared/NetworkMonitorUtils.java
index bb4a603..46e9c73 100644
--- a/services/net/java/android/net/shared/NetworkMonitorUtils.java
+++ b/services/net/java/android/net/shared/NetworkMonitorUtils.java
@@ -43,16 +43,23 @@
"android.permission.ACCESS_NETWORK_CONDITIONS";
/**
- * Return whether validation is required for a network.
- * @param dfltNetCap Default requested network capabilities.
+ * Return whether validation is required for private DNS in strict mode.
* @param nc Network capabilities of the network to test.
*/
- public static boolean isValidationRequired(NetworkCapabilities nc) {
+ public static boolean isPrivateDnsValidationRequired(NetworkCapabilities nc) {
// TODO: Consider requiring validation for DUN networks.
return nc != null
&& nc.hasCapability(NET_CAPABILITY_INTERNET)
&& nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
- && nc.hasCapability(NET_CAPABILITY_TRUSTED)
- && nc.hasCapability(NET_CAPABILITY_NOT_VPN);
+ && nc.hasCapability(NET_CAPABILITY_TRUSTED);
+ }
+
+ /**
+ * Return whether validation is required for a network.
+ * @param nc Network capabilities of the network to test.
+ */
+ public static boolean isValidationRequired(NetworkCapabilities nc) {
+ // TODO: Consider requiring validation for DUN networks.
+ return isPrivateDnsValidationRequired(nc) && nc.hasCapability(NET_CAPABILITY_NOT_VPN);
}
}
diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
index 37909c3..0cb21d0 100644
--- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -17,7 +17,9 @@
package com.android.server.backup;
import static android.Manifest.permission.BACKUP;
+import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.Manifest.permission.PACKAGE_USAGE_STATS;
import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThread;
import static com.android.server.backup.testing.TransportData.backupTransport;
@@ -64,6 +66,7 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.io.StringWriter;
/** Tests for the user-aware backup/restore system service {@link BackupManagerService}. */
@RunWith(RobolectricTestRunner.class)
@@ -1515,6 +1518,8 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testDump_onRegisteredUser_callsMethodForUser() throws Exception {
+ grantDumpPermissions();
+
BackupManagerService backupManagerService =
createServiceAndRegisterUser(UserHandle.USER_SYSTEM, mUserOneService);
File testFile = createTestFile();
@@ -1530,6 +1535,8 @@
/** Test that the backup service does not route methods for non-registered users. */
@Test
public void testDump_onUnknownUser_doesNotPropagateCall() throws Exception {
+ grantDumpPermissions();
+
BackupManagerService backupManagerService = createService();
File testFile = createTestFile();
FileDescriptor fileDescriptor = new FileDescriptor();
@@ -1541,6 +1548,31 @@
verify(mUserOneService, never()).dump(fileDescriptor, printWriter, args);
}
+ /** Test that 'dumpsys backup users' dumps the list of users registered in backup service*/
+ @Test
+ public void testDump_users_dumpsListOfRegisteredUsers() {
+ grantDumpPermissions();
+
+ BackupManagerService backupManagerService = createServiceAndRegisterUser(mUserOneId,
+ mUserOneService);
+ StringWriter out = new StringWriter();
+ PrintWriter writer = new PrintWriter(out);
+ String[] args = {"users"};
+
+ backupManagerService.dump(null, writer, args);
+
+ writer.flush();
+ assertEquals(
+ String.format("%s %d\n", BackupManagerService.DUMP_RUNNING_USERS_MESSAGE,
+ mUserOneId),
+ out.toString());
+ }
+
+ private void grantDumpPermissions() {
+ mShadowContext.grantPermissions(DUMP);
+ mShadowContext.grantPermissions(PACKAGE_USAGE_STATS);
+ }
+
private File createTestFile() throws IOException {
File testFile = new File(mContext.getFilesDir(), "test");
testFile.createNewFile();
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java
new file mode 100644
index 0000000..4538cac
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.color;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Binder;
+import android.os.IBinder;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.DisplayPrimaries;
+import android.view.SurfaceControl.CieXyz;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.R;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+@RunWith(AndroidJUnit4.class)
+public class DisplayWhiteBalanceTintControllerTest {
+ @Mock
+ private Context mMockedContext;
+ @Mock
+ private Resources mMockedResources;
+
+ private MockitoSession mSession;
+ private Resources mResources;
+ IBinder mDisplayToken;
+ DisplayWhiteBalanceTintController mDisplayWhiteBalanceTintController;
+
+ @Before
+ public void setUp() {
+ mSession = ExtendedMockito.mockitoSession()
+ .initMocks(this)
+ .mockStatic(SurfaceControl.class)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
+
+ mResources = InstrumentationRegistry.getContext().getResources();
+ // These Resources are common to all tests.
+ doReturn(mResources.getInteger(R.integer.config_displayWhiteBalanceColorTemperatureMin))
+ .when(mMockedResources)
+ .getInteger(R.integer.config_displayWhiteBalanceColorTemperatureMin);
+ doReturn(mResources.getInteger(R.integer.config_displayWhiteBalanceColorTemperatureMax))
+ .when(mMockedResources)
+ .getInteger(R.integer.config_displayWhiteBalanceColorTemperatureMax);
+ doReturn(mResources.getInteger(R.integer.config_displayWhiteBalanceColorTemperatureDefault))
+ .when(mMockedResources)
+ .getInteger(R.integer.config_displayWhiteBalanceColorTemperatureDefault);
+ doReturn(mResources.getStringArray(R.array.config_displayWhiteBalanceDisplayNominalWhite))
+ .when(mMockedResources)
+ .getStringArray(R.array.config_displayWhiteBalanceDisplayNominalWhite);
+ doReturn(mMockedResources).when(mMockedContext).getResources();
+
+ mDisplayToken = new Binder();
+ doReturn(mDisplayToken).when(() -> SurfaceControl.getInternalDisplayToken());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mSession != null) {
+ mSession.finishMocking();
+ }
+ }
+
+ /**
+ * Setup should succeed when SurfaceControl setup results in a valid color transform.
+ */
+ @Test
+ public void displayWhiteBalance_setupWithSurfaceControl() {
+ // Make SurfaceControl return sRGB primaries
+ DisplayPrimaries displayPrimaries = new DisplayPrimaries();
+ displayPrimaries.red = new CieXyz();
+ displayPrimaries.red.X = 0.412315f;
+ displayPrimaries.red.Y = 0.212600f;
+ displayPrimaries.red.Z = 0.019327f;
+ displayPrimaries.green = new CieXyz();
+ displayPrimaries.green.X = 0.357600f;
+ displayPrimaries.green.Y = 0.715200f;
+ displayPrimaries.green.Z = 0.119200f;
+ displayPrimaries.blue = new CieXyz();
+ displayPrimaries.blue.X = 0.180500f;
+ displayPrimaries.blue.Y = 0.072200f;
+ displayPrimaries.blue.Z = 0.950633f;
+ displayPrimaries.white = new CieXyz();
+ displayPrimaries.white.X = 0.950456f;
+ displayPrimaries.white.Y = 1.000000f;
+ displayPrimaries.white.Z = 1.089058f;
+ doReturn(displayPrimaries)
+ .when(() -> SurfaceControl.getDisplayNativePrimaries(mDisplayToken));
+
+ setUpTintController();
+ assertWithMessage("Setup with valid SurfaceControl failed")
+ .that(mDisplayWhiteBalanceTintController.mSetUp)
+ .isTrue();
+ }
+
+ /**
+ * Setup should fail when SurfaceControl setup results in an invalid color transform.
+ */
+ @Test
+ public void displayWhiteBalance_setupWithInvalidSurfaceControlData() {
+ // Make SurfaceControl return invalid display primaries
+ DisplayPrimaries displayPrimaries = new DisplayPrimaries();
+ displayPrimaries.red = new CieXyz();
+ displayPrimaries.green = new CieXyz();
+ displayPrimaries.blue = new CieXyz();
+ displayPrimaries.white = new CieXyz();
+ doReturn(displayPrimaries)
+ .when(() -> SurfaceControl.getDisplayNativePrimaries(mDisplayToken));
+
+ setUpTintController();
+ assertWithMessage("Setup with invalid SurfaceControl succeeded")
+ .that(mDisplayWhiteBalanceTintController.mSetUp)
+ .isFalse();
+ }
+
+ /**
+ * Setup should succeed when SurfaceControl setup fails and Resources result in a valid color
+ * transform.
+ */
+ @Test
+ public void displayWhiteBalance_setupWithResources() {
+ // Use default (valid) Resources
+ doReturn(mResources.getStringArray(R.array.config_displayWhiteBalanceDisplayPrimaries))
+ .when(mMockedResources)
+ .getStringArray(R.array.config_displayWhiteBalanceDisplayPrimaries);
+ // Make SurfaceControl setup fail
+ doReturn(null).when(() -> SurfaceControl.getDisplayNativePrimaries(mDisplayToken));
+
+ setUpTintController();
+ assertWithMessage("Setup with valid Resources failed")
+ .that(mDisplayWhiteBalanceTintController.mSetUp)
+ .isTrue();
+ }
+
+ /**
+ * Setup should fail when SurfaceControl setup fails and Resources result in an invalid color
+ * transform.
+ */
+ @Test
+ public void displayWhiteBalance_setupWithInvalidResources() {
+ // Use Resources with invalid color data
+ doReturn(new String[] {
+ "0", "0", "0", // Red X, Y, Z
+ "0", "0", "0", // Green X, Y, Z
+ "0", "0", "0", // Blue X, Y, Z
+ "0", "0", "0", // White X, Y, Z
+ })
+ .when(mMockedResources)
+ .getStringArray(R.array.config_displayWhiteBalanceDisplayPrimaries);
+ // Make SurfaceControl setup fail
+ doReturn(null).when(() -> SurfaceControl.getDisplayNativePrimaries(mDisplayToken));
+
+ setUpTintController();
+ assertWithMessage("Setup with invalid Resources succeeded")
+ .that(mDisplayWhiteBalanceTintController.mSetUp)
+ .isFalse();
+ }
+
+ private void setUpTintController() {
+ mDisplayWhiteBalanceTintController = new DisplayWhiteBalanceTintController();
+ mDisplayWhiteBalanceTintController.setUp(mMockedContext, true);
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index f7edf65..18c524a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -183,15 +183,188 @@
assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
- advanceElapsedClock(45 * MINUTE_IN_MILLIS); // now + 55 minutes
+ advanceElapsedClock(20 * MINUTE_IN_MILLIS); // now + 30 minutes
rescheduledJob = mService.getRescheduleJobForPeriodic(job);
assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+ advanceElapsedClock(25 * MINUTE_IN_MILLIS); // now + 55 minutes
+
+ rescheduledJob = mService.getRescheduleJobForPeriodic(job);
+ // Shifted because it's close to the end of the window.
+ assertEquals(nextWindowStartTime + 5 * MINUTE_IN_MILLIS,
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
advanceElapsedClock(4 * MINUTE_IN_MILLIS); // now + 59 minutes
rescheduledJob = mService.getRescheduleJobForPeriodic(job);
+ // Shifted because it's close to the end of the window.
+ assertEquals(nextWindowStartTime + 9 * MINUTE_IN_MILLIS,
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+ }
+
+ /**
+ * Confirm that {@link JobSchedulerService#getRescheduleJobForPeriodic(JobStatus)} returns a job
+ * with an extra delay and correct deadline constraint if the periodic job is completed near the
+ * end of its expected running window.
+ */
+ @Test
+ public void testGetRescheduleJobForPeriodic_closeToEndOfWindow() {
+ JobStatus frequentJob = createJobStatus(
+ "testGetRescheduleJobForPeriodic_closeToEndOfWindow",
+ createJobInfo().setPeriodic(15 * MINUTE_IN_MILLIS));
+ long now = sElapsedRealtimeClock.millis();
+ long nextWindowStartTime = now + 15 * MINUTE_IN_MILLIS;
+ long nextWindowEndTime = now + 30 * MINUTE_IN_MILLIS;
+
+ // At the beginning of the window. Next window should be unaffected.
+ JobStatus rescheduledJob = mService.getRescheduleJobForPeriodic(frequentJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Halfway through window. Next window should be unaffected.
+ advanceElapsedClock((long) (7.5 * MINUTE_IN_MILLIS));
+ rescheduledJob = mService.getRescheduleJobForPeriodic(frequentJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window start time should be shifted slightly.
+ advanceElapsedClock(6 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(frequentJob);
+ assertEquals(nextWindowStartTime + MINUTE_IN_MILLIS,
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ JobStatus mediumJob = createJobStatus("testGetRescheduleJobForPeriodic_closeToEndOfWindow",
+ createJobInfo().setPeriodic(HOUR_IN_MILLIS));
+ now = sElapsedRealtimeClock.millis();
+ nextWindowStartTime = now + HOUR_IN_MILLIS;
+ nextWindowEndTime = now + 2 * HOUR_IN_MILLIS;
+
+ // At the beginning of the window. Next window should be unaffected.
+ rescheduledJob = mService.getRescheduleJobForPeriodic(mediumJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Halfway through window. Next window should be unaffected.
+ advanceElapsedClock(30 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(mediumJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // At the edge 1/6 of window. Next window should be unaffected.
+ advanceElapsedClock(20 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(mediumJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window start time should be shifted slightly.
+ advanceElapsedClock(6 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(mediumJob);
+ assertEquals(nextWindowStartTime + (6 * MINUTE_IN_MILLIS),
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ JobStatus longJob = createJobStatus("testGetRescheduleJobForPeriodic_closeToEndOfWindow",
+ createJobInfo().setPeriodic(6 * HOUR_IN_MILLIS));
+ now = sElapsedRealtimeClock.millis();
+ nextWindowStartTime = now + 6 * HOUR_IN_MILLIS;
+ nextWindowEndTime = now + 12 * HOUR_IN_MILLIS;
+
+ // At the beginning of the window. Next window should be unaffected.
+ rescheduledJob = mService.getRescheduleJobForPeriodic(longJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Halfway through window. Next window should be unaffected.
+ advanceElapsedClock(3 * HOUR_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(longJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // At the edge 1/6 of window. Next window should be unaffected.
+ advanceElapsedClock(2 * HOUR_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(longJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window should be unaffected since we're over the shift cap.
+ advanceElapsedClock(15 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(longJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window start time should be shifted slightly.
+ advanceElapsedClock(30 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(longJob);
+ assertEquals(nextWindowStartTime + (30 * MINUTE_IN_MILLIS),
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Flex duration close to period duration.
+ JobStatus gameyFlex = createJobStatus("testGetRescheduleJobForPeriodic_closeToEndOfWindow",
+ createJobInfo().setPeriodic(HOUR_IN_MILLIS, 59 * MINUTE_IN_MILLIS));
+ now = sElapsedRealtimeClock.millis();
+ nextWindowStartTime = now + HOUR_IN_MILLIS + MINUTE_IN_MILLIS;
+ nextWindowEndTime = now + 2 * HOUR_IN_MILLIS;
+ advanceElapsedClock(MINUTE_IN_MILLIS);
+
+ // At the beginning of the window. Next window should be unaffected.
+ rescheduledJob = mService.getRescheduleJobForPeriodic(gameyFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Halfway through window. Next window should be unaffected.
+ advanceElapsedClock(29 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(gameyFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // At the edge 1/6 of window. Next window should be unaffected.
+ advanceElapsedClock(20 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(gameyFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window start time should be shifted slightly.
+ advanceElapsedClock(6 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(gameyFlex);
+ assertEquals(nextWindowStartTime + (5 * MINUTE_IN_MILLIS),
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Very short flex duration compared to period duration.
+ JobStatus superFlex = createJobStatus("testGetRescheduleJobForPeriodic_closeToEndOfWindow",
+ createJobInfo().setPeriodic(HOUR_IN_MILLIS, 10 * MINUTE_IN_MILLIS));
+ now = sElapsedRealtimeClock.millis();
+ nextWindowStartTime = now + HOUR_IN_MILLIS + 50 * MINUTE_IN_MILLIS;
+ nextWindowEndTime = now + 2 * HOUR_IN_MILLIS;
+ advanceElapsedClock(MINUTE_IN_MILLIS);
+
+ // At the beginning of the window. Next window should be unaffected.
+ rescheduledJob = mService.getRescheduleJobForPeriodic(superFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Halfway through window. Next window should be unaffected.
+ advanceElapsedClock(29 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(superFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // At the edge 1/6 of window. Next window should be unaffected.
+ advanceElapsedClock(20 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(superFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window should be unaffected since the flex duration pushes
+ // the next window start time far enough away.
+ advanceElapsedClock(6 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(superFlex);
assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
}
@@ -265,7 +438,9 @@
advanceElapsedClock(10 * MINUTE_IN_MILLIS); // now + 55 minutes
rescheduledJob = mService.getRescheduleJobForPeriodic(failedJob);
- assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ // Shifted because it's close to the end of the window.
+ assertEquals(nextWindowStartTime + 5 * MINUTE_IN_MILLIS,
+ rescheduledJob.getEarliestRunTime());
assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
advanceElapsedClock(2 * MINUTE_IN_MILLIS); // now + 57 minutes
@@ -273,7 +448,9 @@
advanceElapsedClock(2 * MINUTE_IN_MILLIS); // now + 59 minutes
rescheduledJob = mService.getRescheduleJobForPeriodic(failedJob);
- assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ // Shifted because it's close to the end of the window.
+ assertEquals(nextWindowStartTime + 9 * MINUTE_IN_MILLIS,
+ rescheduledJob.getEarliestRunTime());
assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
}
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 01f2f6b..25bd4ec 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -69,6 +69,7 @@
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
<uses-permission android:name="android.permission.HARDWARE_TEST"/>
+ <uses-permission android:name="android.permission.MANAGE_APPOPS"/>
<!-- Uses API introduced in O (26) -->
<uses-sdk android:minSdkVersion="1"
diff --git a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
index 68f696b..d192748 100644
--- a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
@@ -15,31 +15,21 @@
*/
package com.android.server;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
-import android.app.ActivityManagerInternal;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
-import android.os.UserManagerInternal;
import android.os.storage.StorageManagerInternal;
-import com.android.internal.os.Zygote;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class StorageManagerServiceTest {
@@ -49,28 +39,6 @@
@Mock private Context mContext;
@Mock private PackageManager mPm;
@Mock private PackageManagerInternal mPmi;
- @Mock private UserManagerInternal mUmi;
- @Mock private ActivityManagerInternal mAmi;
-
- private static final String PKG_GREY = "com.grey";
- private static final String PKG_RED = "com.red";
- private static final String PKG_BLUE = "com.blue";
-
- private static final int UID_GREY = 10000;
- private static final int UID_COLORS = 10001;
-
- private static final int PID_GREY = 1111;
- private static final int PID_RED = 2222;
- private static final int PID_BLUE = 3333;
-
- private static final String NAME_COLORS = "colors";
-
- private static ApplicationInfo buildApplicationInfo(String packageName, int uid) {
- final ApplicationInfo ai = new ApplicationInfo();
- ai.packageName = packageName;
- ai.uid = uid;
- return ai;
- }
@Before
public void setUp() throws Exception {
@@ -80,196 +48,9 @@
LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.addService(PackageManagerInternal.class, mPmi);
- LocalServices.removeServiceForTest(UserManagerInternal.class);
- LocalServices.addService(UserManagerInternal.class, mUmi);
- LocalServices.removeServiceForTest(ActivityManagerInternal.class);
- LocalServices.addService(ActivityManagerInternal.class, mAmi);
when(mContext.getPackageManager()).thenReturn(mPm);
- when(mUmi.getUserIds()).thenReturn(new int[] { 0 });
-
- when(mPmi.getSharedUserIdForPackage(eq(PKG_GREY))).thenReturn(null);
- when(mPmi.getSharedUserIdForPackage(eq(PKG_RED))).thenReturn(NAME_COLORS);
- when(mPmi.getSharedUserIdForPackage(eq(PKG_BLUE))).thenReturn(NAME_COLORS);
-
- when(mPmi.getPackagesForSharedUserId(eq(NAME_COLORS), anyInt()))
- .thenReturn(new String[] { PKG_RED, PKG_BLUE });
-
- when(mPm.getPackagesForUid(eq(UID_GREY))).thenReturn(new String[] { PKG_GREY });
- when(mPm.getPackagesForUid(eq(UID_COLORS))).thenReturn(new String[] { PKG_RED, PKG_BLUE });
-
- setStorageMountMode(PID_BLUE, UID_COLORS, Zygote.MOUNT_EXTERNAL_WRITE);
- setStorageMountMode(PID_GREY, UID_GREY, Zygote.MOUNT_EXTERNAL_WRITE);
- setStorageMountMode(PID_RED, UID_COLORS, Zygote.MOUNT_EXTERNAL_WRITE);
-
mService = new StorageManagerService(mContext);
}
-
- private void setStorageMountMode(int pid, int uid, int mountMode) {
- when(mAmi.getStorageMountMode(pid, uid)).thenReturn(mountMode);
- }
-
- @Test
- public void testNone() throws Exception {
- assertTranslation(
- "/dev/null",
- "/dev/null", PID_GREY, UID_GREY);
- assertTranslation(
- "/dev/null",
- "/dev/null", PID_RED, UID_COLORS);
- }
-
- @Test
- public void testPrimary() throws Exception {
- assertTranslation(
- "/storage/emulated/0/Android/sandbox/com.grey/foo.jpg",
- "/storage/emulated/0/foo.jpg",
- PID_GREY, UID_GREY);
- assertTranslation(
- "/storage/emulated/0/Android/sandbox/shared-colors/foo.jpg",
- "/storage/emulated/0/foo.jpg",
- PID_RED, UID_COLORS);
- }
-
- @Test
- public void testSecondary() throws Exception {
- assertTranslation(
- "/storage/0000-0000/Android/sandbox/com.grey/foo/bar.jpg",
- "/storage/0000-0000/foo/bar.jpg",
- PID_GREY, UID_GREY);
- assertTranslation(
- "/storage/0000-0000/Android/sandbox/shared-colors/foo/bar.jpg",
- "/storage/0000-0000/foo/bar.jpg",
- PID_RED, UID_COLORS);
- }
-
- @Test
- public void testLegacy() throws Exception {
- // Accessing their own paths goes straight through
- assertTranslation(
- "/storage/emulated/0/Android/data/com.grey/foo.jpg",
- "/storage/emulated/0/Android/data/com.grey/foo.jpg",
- PID_GREY, UID_GREY);
-
- // Accessing other package paths goes into sandbox
- assertTranslation(
- "/storage/emulated/0/Android/sandbox/shared-colors/"
- + "Android/data/com.grey/foo.jpg",
- "/storage/emulated/0/Android/data/com.grey/foo.jpg",
- PID_RED, UID_COLORS);
- }
-
- @Test
- public void testLegacyShared() throws Exception {
- // Accessing their own paths goes straight through
- assertTranslation(
- "/storage/emulated/0/Android/data/com.red/foo.jpg",
- "/storage/emulated/0/Android/data/com.red/foo.jpg",
- PID_RED, UID_COLORS);
- assertTranslation(
- "/storage/emulated/0/Android/data/com.red/foo.jpg",
- "/storage/emulated/0/Android/data/com.red/foo.jpg",
- PID_BLUE, UID_COLORS);
-
- // Accessing other package paths goes into sandbox
- assertTranslation(
- "/storage/emulated/0/Android/sandbox/com.grey/"
- + "Android/data/com.red/foo.jpg",
- "/storage/emulated/0/Android/data/com.red/foo.jpg",
- PID_GREY, UID_GREY);
- }
-
- @Test
- public void testSecurity() throws Exception {
- // Shady paths should throw
- try {
- mService.translateAppToSystem(
- "/storage/emulated/0/../foo.jpg",
- PID_GREY, UID_GREY);
- fail();
- } catch (SecurityException expected) {
- }
-
- // Sandboxes can't see system paths
- try {
- mService.translateSystemToApp(
- "/storage/emulated/0/foo.jpg",
- PID_GREY, UID_GREY);
- fail();
- } catch (SecurityException expected) {
- }
-
- // Sandboxes can't see paths in other sandboxes
- try {
- mService.translateSystemToApp(
- "/storage/emulated/0/Android/sandbox/shared-colors/foo.jpg",
- PID_GREY, UID_GREY);
- fail();
- } catch (SecurityException expected) {
- }
- }
-
- @Test
- public void testPackageNotSandboxed() throws Exception {
- setStorageMountMode(PID_RED, UID_COLORS, Zygote.MOUNT_EXTERNAL_FULL);
-
- // Both app and system have the same view
- assertTranslation(
- "/storage/emulated/0/Android/data/com.red/foo.jpg",
- "/storage/emulated/0/Android/data/com.red/foo.jpg",
- PID_RED, UID_COLORS);
-
- assertTranslation(
- "/storage/emulated/0/Android/sandbox/com.grey/bar.jpg",
- "/storage/emulated/0/Android/sandbox/com.grey/bar.jpg",
- PID_RED, UID_COLORS);
- }
-
- @Test
- public void testPackageInLegacyMode() throws Exception {
- setStorageMountMode(PID_RED, UID_COLORS, Zygote.MOUNT_EXTERNAL_LEGACY);
-
- // Both app and system have the same view
- assertTranslation(
- "/storage/emulated/0/Android/data/com.red/foo.jpg",
- "/storage/emulated/0/Android/data/com.red/foo.jpg",
- PID_RED, UID_COLORS);
-
- assertTranslation(
- "/storage/emulated/0/Android/sandbox/com.grey/bar.jpg",
- "/storage/emulated/0/Android/sandbox/com.grey/bar.jpg",
- PID_RED, UID_COLORS);
- }
-
- @Test
- public void testInstallerPackage() throws Exception {
- setStorageMountMode(PID_GREY, UID_GREY, Zygote.MOUNT_EXTERNAL_INSTALLER);
-
- assertTranslation(
- "/storage/emulated/0/Android/obb/com.grey/foo.jpg",
- "/storage/emulated/0/Android/obb/com.grey/foo.jpg",
- PID_GREY, UID_GREY);
- assertTranslation(
- "/storage/emulated/0/Android/obb/com.blue/bar.jpg",
- "/storage/emulated/0/Android/obb/com.blue/bar.jpg",
- PID_GREY, UID_GREY);
-
- assertTranslation(
- "/storage/emulated/0/Android/data/com.grey/foo.jpg",
- "/storage/emulated/0/Android/data/com.grey/foo.jpg",
- PID_GREY, UID_GREY);
- assertTranslation(
- "/storage/emulated/0/Android/sandbox/com.grey/Android/data/com.blue/bar.jpg",
- "/storage/emulated/0/Android/data/com.blue/bar.jpg",
- PID_GREY, UID_GREY);
- }
-
- private void assertTranslation(String system, String sandbox,
- int pid, int uid) throws Exception {
- assertEquals(system,
- mService.translateAppToSystem(sandbox, pid, uid));
- assertEquals(sandbox,
- mService.translateSystemToApp(system, pid, uid));
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
index 65af677..d4182f3 100644
--- a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
@@ -37,7 +37,10 @@
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.io.BufferedReader;
import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
@@ -57,8 +60,8 @@
+ "com.android.server.adb.AdbDebuggingManagerTestActivity";
// The base64 encoding of the values 'test key 1' and 'test key 2'.
- private static final String TEST_KEY_1 = "dGVzdCBrZXkgMQo=";
- private static final String TEST_KEY_2 = "dGVzdCBrZXkgMgo=";
+ private static final String TEST_KEY_1 = "dGVzdCBrZXkgMQo= test@android.com";
+ private static final String TEST_KEY_2 = "dGVzdCBrZXkgMgo= test@android.com";
// This response is received from the AdbDebuggingHandler when the key is allowed to connect
private static final String RESPONSE_KEY_ALLOWED = "OK";
@@ -76,22 +79,26 @@
private AdbDebuggingManager.AdbKeyStore mKeyStore;
private BlockingQueue<TestResult> mBlockingQueue;
private long mOriginalAllowedConnectionTime;
- private File mKeyFile;
+ private File mAdbKeyXmlFile;
+ private File mAdbKeyFile;
@Before
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getContext();
- mManager = new AdbDebuggingManager(mContext, ADB_CONFIRM_COMPONENT);
- mKeyFile = new File(mContext.getFilesDir(), "test_adb_keys.xml");
- if (mKeyFile.exists()) {
- mKeyFile.delete();
+ mAdbKeyFile = new File(mContext.getFilesDir(), "adb_keys");
+ if (mAdbKeyFile.exists()) {
+ mAdbKeyFile.delete();
+ }
+ mManager = new AdbDebuggingManager(mContext, ADB_CONFIRM_COMPONENT, mAdbKeyFile);
+ mAdbKeyXmlFile = new File(mContext.getFilesDir(), "test_adb_keys.xml");
+ if (mAdbKeyXmlFile.exists()) {
+ mAdbKeyXmlFile.delete();
}
mThread = new AdbDebuggingThreadTest();
- mKeyStore = mManager.new AdbKeyStore(mKeyFile);
+ mKeyStore = mManager.new AdbKeyStore(mAdbKeyXmlFile);
mHandler = mManager.new AdbDebuggingHandler(FgThread.get().getLooper(), mThread, mKeyStore);
mOriginalAllowedConnectionTime = mKeyStore.getAllowedConnectionTime();
mBlockingQueue = new ArrayBlockingQueue<>(1);
-
}
@After
@@ -118,6 +125,13 @@
// Verify if the user allows the key but does not select the option to 'always
// allow' that the connection is allowed but the key is not stored.
runAdbTest(TEST_KEY_1, true, false, false);
+
+ // Persist the keystore to ensure that the key is not written to the adb_keys file.
+ persistKeyStore();
+ assertFalse(
+ "A key for which the 'always allow' option is not selected must not be written "
+ + "to the adb_keys file",
+ isKeyInFile(TEST_KEY_1, mAdbKeyFile));
}
@Test
@@ -146,25 +160,11 @@
// Send the disconnect message for the currently connected key to trigger an update of the
// last connection time.
- mHandler.obtainMessage(
- AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_DISCONNECT).sendToTarget();
-
- // Use a latch to ensure the test does not exit untill the Runnable has been processed.
- CountDownLatch latch = new CountDownLatch(1);
-
- // Post a new Runnable to the handler to ensure it runs after the disconnect message is
- // processed.
- mHandler.post(() -> {
- assertNotEquals(
- "The last connection time was not updated after the disconnect",
- lastConnectionTime,
- mKeyStore.getLastConnectionTime(TEST_KEY_1));
- latch.countDown();
- });
- if (!latch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
- fail("The Runnable to verify the last connection time was updated did not complete "
- + "within the timeout period");
- }
+ disconnectKey(TEST_KEY_1);
+ assertNotEquals(
+ "The last connection time was not updated after the disconnect",
+ lastConnectionTime,
+ mKeyStore.getLastConnectionTime(TEST_KEY_1));
}
@Test
@@ -177,8 +177,7 @@
runAdbTest(TEST_KEY_1, true, false, false);
// Send the disconnect message for the currently connected key.
- mHandler.obtainMessage(
- AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_DISCONNECT).sendToTarget();
+ disconnectKey(TEST_KEY_1);
// Verify that the disconnected key is not automatically allowed on a subsequent connection.
runAdbTest(TEST_KEY_1, true, false, false);
@@ -192,12 +191,13 @@
// Allow a connection from a new key with the 'Always allow' option selected.
runAdbTest(TEST_KEY_1, true, true, false);
- // Next attempt another connection with the same key and verify that the activity to prompt
- // the user to accept the key is not launched.
- runAdbTest(TEST_KEY_1, true, true, true);
+ // Send a persist keystore message to force the key to be written to the adb_keys file
+ persistKeyStore();
- // Verify that a different key is not automatically allowed.
- runAdbTest(TEST_KEY_2, false, false, false);
+ // Verify the key is in the adb_keys file to ensure subsequent connections are allowed by
+ // adbd.
+ assertTrue("The key was not in the adb_keys file after persisting the keystore",
+ isKeyInFile(TEST_KEY_1, mAdbKeyFile));
}
@Test
@@ -215,8 +215,11 @@
// fail the new test but would be allowed with the original behavior.
mKeyStore.setLastConnectionTime(TEST_KEY_1, 1);
- // Run the test with the key and verify that the connection is automatically allowed.
- runAdbTest(TEST_KEY_1, true, true, true);
+ // Verify that the key is in the adb_keys file to ensure subsequent connections are
+ // automatically allowed by adbd.
+ persistKeyStore();
+ assertTrue("The key was not in the adb_keys file after persisting the keystore",
+ isKeyInFile(TEST_KEY_1, mAdbKeyFile));
}
@Test
@@ -237,24 +240,11 @@
Thread.sleep(10);
// Send a message to the handler to update the last connection time for the active key
- mHandler.obtainMessage(
- AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_UPDATE_KEY_CONNECTION_TIME)
- .sendToTarget();
-
- // Post a Runnable to the handler to ensure it runs after the update key connection time
- // message is processed.
- CountDownLatch latch = new CountDownLatch(1);
- mHandler.post(() -> {
- assertNotEquals(
- "The last connection time of the key was not updated after the update key "
- + "connection time message",
- lastConnectionTime, mKeyStore.getLastConnectionTime(TEST_KEY_1));
- latch.countDown();
- });
- if (!latch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
- fail("The Runnable to verify the last connection time was updated did not complete "
- + "within the timeout period");
- }
+ updateKeyStore();
+ assertNotEquals(
+ "The last connection time of the key was not updated after the update key "
+ + "connection time message",
+ lastConnectionTime, mKeyStore.getLastConnectionTime(TEST_KEY_1));
}
@Test
@@ -266,16 +256,12 @@
// Allow the key to connect with the 'Always allow' option selected
runAdbTest(TEST_KEY_1, true, true, false);
- // Send a message to the handler to persist the updated keystore.
- mHandler.obtainMessage(
- AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_PERSIST_KEY_STORE)
- .sendToTarget();
-
- // Post a Runnable to the handler to ensure the persist key store message has been processed
- // using a new AdbKeyStore backed by the key file.
- mHandler.post(() -> assertTrue(
+ // Send a message to the handler to persist the updated keystore and verify a new key store
+ // backed by the XML file contains the key.
+ persistKeyStore();
+ assertTrue(
"The key with the 'Always allow' option selected was not persisted in the keystore",
- mManager.new AdbKeyStore(mKeyFile).isKeyAuthorized(TEST_KEY_1)));
+ mManager.new AdbKeyStore(mAdbKeyXmlFile).isKeyAuthorized(TEST_KEY_1));
// Get the current last connection time to ensure it is updated in the persisted keystore.
long lastConnectionTime = mKeyStore.getLastConnectionTime(TEST_KEY_1);
@@ -284,29 +270,18 @@
Thread.sleep(10);
// Send a message to the handler to update the last connection time for the active key.
- mHandler.obtainMessage(
- AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_UPDATE_KEY_CONNECTION_TIME)
- .sendToTarget();
+ updateKeyStore();
- // Persist the updated last connection time.
- mHandler.obtainMessage(
- AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_PERSIST_KEY_STORE)
- .sendToTarget();
-
- // Post a Runnable with a new key store backed by the key file to verify that the last
- // connection time obtained above is different from the persisted updated value.
- CountDownLatch latch = new CountDownLatch(1);
- mHandler.post(() -> {
- assertNotEquals(
- "The last connection time in the key file was not updated after the update "
- + "connection time message", lastConnectionTime,
- mManager.new AdbKeyStore(mKeyFile).getLastConnectionTime(TEST_KEY_1));
- latch.countDown();
- });
- if (!latch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
- fail("The Runnable to verify the last connection time was updated did not complete "
- + "within the timeout period");
- }
+ // Persist the updated last connection time and verify a new key store backed by the XML
+ // file contains the updated connection time.
+ persistKeyStore();
+ assertNotEquals(
+ "The last connection time in the key file was not updated after the update "
+ + "connection time message", lastConnectionTime,
+ mManager.new AdbKeyStore(mAdbKeyXmlFile).getLastConnectionTime(TEST_KEY_1));
+ // Verify that the key is in the adb_keys file
+ assertTrue("The key was not in the adb_keys file after persisting the keystore",
+ isKeyInFile(TEST_KEY_1, mAdbKeyFile));
}
@Test
@@ -318,28 +293,18 @@
runAdbTest(TEST_KEY_1, true, true, false);
// Send a message to the handler to clear the adb authorizations.
- mHandler.obtainMessage(
- AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_CLEAR).sendToTarget();
+ clearKeyStore();
// Send a message to disconnect the currently connected key
- mHandler.obtainMessage(
- AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_DISCONNECT).sendToTarget();
+ disconnectKey(TEST_KEY_1);
+ assertFalse(
+ "The currently connected 'always allow' key must not be authorized after an adb"
+ + " clear message.",
+ mKeyStore.isKeyAuthorized(TEST_KEY_1));
- // Post a Runnable to ensure the disconnect has completed to verify the 'Always allow' key
- // that was connected when the clear was sent requires authorization.
- CountDownLatch latch = new CountDownLatch(1);
- mHandler.post(() -> {
- assertFalse(
- "The currently connected 'always allow' key should not be authorized after an"
- + " adb"
- + " clear message.",
- mKeyStore.isKeyAuthorized(TEST_KEY_1));
- latch.countDown();
- });
- if (!latch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
- fail("The Runnable to verify the key is not authorized did not complete within the "
- + "timeout period");
- }
+ // The key should not be in the adb_keys file after clearing the authorizations.
+ assertFalse("The key must not be in the adb_keys file after clearing authorizations",
+ isKeyInFile(TEST_KEY_1, mAdbKeyFile));
}
@Test
@@ -357,8 +322,17 @@
// Sleep for a small amount of time to exceed the allowed window.
Thread.sleep(10);
- // A new connection from this key should prompt the user again.
- runAdbTest(TEST_KEY_1, true, true, false);
+ // The AdbKeyStore has a method to get the time of the next key expiration to ensure the
+ // scheduled job runs at the time of the next expiration or after 24 hours, whichever occurs
+ // first.
+ assertEquals("The time of the next key expiration must be 0.", 0,
+ mKeyStore.getNextExpirationTime());
+
+ // Persist the key store and verify that the key is no longer in the adb_keys file.
+ persistKeyStore();
+ assertFalse(
+ "The key must not be in the adb_keys file after the allowed time has elapsed.",
+ isKeyInFile(TEST_KEY_1, mAdbKeyFile));
}
@Test
@@ -381,7 +355,7 @@
// Attempt to set the last connection time to 1970
mKeyStore.setLastConnectionTime(TEST_KEY_1, 0);
assertEquals(
- "The last connection time in the adb key store should not be set to a value less "
+ "The last connection time in the adb key store must not be set to a value less "
+ "than the previous connection time",
lastConnectionTime, mKeyStore.getLastConnectionTime(TEST_KEY_1));
@@ -389,11 +363,315 @@
mKeyStore.setLastConnectionTime(TEST_KEY_1,
Math.max(0, lastConnectionTime - (mKeyStore.getAllowedConnectionTime() + 1)));
assertEquals(
- "The last connection time in the adb key store should not be set to a value less "
+ "The last connection time in the adb key store must not be set to a value less "
+ "than the previous connection time",
lastConnectionTime, mKeyStore.getLastConnectionTime(TEST_KEY_1));
}
+ @Test
+ public void testAdbKeyRemovedByScheduledJob() throws Exception {
+ // When a key is automatically allowed it should be stored in the adb_keys file. A job is
+ // then scheduled daily to update the connection time of the currently connected key, and if
+ // no connected key exists the key store is updated to purge expired keys. This test
+ // verifies that after a key's expiration time has been reached that it is no longer
+ // in the key store nor the adb_keys file
+
+ // Set the allowed time to the default to ensure that any modification to this value do not
+ // impact this test.
+ setAllowedConnectionTime(Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME);
+
+ // Allow both test keys to connect with the 'always allow' option selected.
+ runAdbTest(TEST_KEY_1, true, true, false);
+ runAdbTest(TEST_KEY_2, true, true, false);
+ disconnectKey(TEST_KEY_1);
+ disconnectKey(TEST_KEY_2);
+
+ // Persist the key store and verify that both keys are in the key store and adb_keys file.
+ persistKeyStore();
+ assertTrue(
+ "Test key 1 must be in the adb_keys file after selecting the 'always allow' "
+ + "option",
+ isKeyInFile(TEST_KEY_1, mAdbKeyFile));
+ assertTrue(
+ "Test key 1 must be in the adb key store after selecting the 'always allow' "
+ + "option",
+ mKeyStore.isKeyAuthorized(TEST_KEY_1));
+ assertTrue(
+ "Test key 2 must be in the adb_keys file after selecting the 'always allow' "
+ + "option",
+ isKeyInFile(TEST_KEY_2, mAdbKeyFile));
+ assertTrue(
+ "Test key 2 must be in the adb key store after selecting the 'always allow' option",
+ mKeyStore.isKeyAuthorized(TEST_KEY_2));
+
+ // Set test key 1's last connection time to a small value and persist the keystore to ensure
+ // it is cleared out after the next key store update.
+ mKeyStore.setLastConnectionTime(TEST_KEY_1, 1, true);
+ updateKeyStore();
+ assertFalse(
+ "Test key 1 must no longer be in the adb_keys file after its timeout period is "
+ + "reached",
+ isKeyInFile(TEST_KEY_1, mAdbKeyFile));
+ assertFalse(
+ "Test key 1 must no longer be in the adb key store after its timeout period is "
+ + "reached",
+ mKeyStore.isKeyAuthorized(TEST_KEY_1));
+ assertTrue(
+ "Test key 2 must still be in the adb_keys file after test key 1's timeout "
+ + "period is reached",
+ isKeyInFile(TEST_KEY_2, mAdbKeyFile));
+ assertTrue(
+ "Test key 2 must still be in the adb key store after test key 1's timeout period "
+ + "is reached",
+ mKeyStore.isKeyAuthorized(TEST_KEY_2));
+ }
+
+ @Test
+ public void testKeystoreExpirationTimes() throws Exception {
+ // When one or more keys are always allowed a daily job is scheduled to update the
+ // connection time of the connected key and to purge any expired keys. The keystore provides
+ // a method to obtain the expiration time of the next key to expire to ensure that a
+ // scheduled job can run at the time of the next expiration if it is before the daily job
+ // would run. This test verifies that this method returns the expected values depending on
+ // when the key should expire and also verifies that the method to schedule the next job to
+ // update the keystore is the expected value based on the time of the next expiration.
+
+ final long epsilon = 5000;
+
+ // Ensure the allowed time is set to the default.
+ setAllowedConnectionTime(Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME);
+
+ // If there are no keys in the keystore the expiration time should be -1.
+ assertEquals("The expiration time must be -1 when there are no keys in the keystore", -1,
+ mKeyStore.getNextExpirationTime());
+
+ // Allow the test key to connect with the 'always allow' option.
+ runAdbTest(TEST_KEY_1, true, true, false);
+
+ // Verify that the current expiration time is within a small value of the default time.
+ long expirationTime = mKeyStore.getNextExpirationTime();
+ if (Math.abs(expirationTime - Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME)
+ > epsilon) {
+ fail("The expiration time for a new key, " + expirationTime
+ + ", is outside the expected value of "
+ + Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME);
+ }
+ // The delay until the next job should be the lesser of the default expiration time and the
+ // AdbDebuggingHandler's job interval.
+ long expectedValue = Math.min(
+ AdbDebuggingManager.AdbDebuggingHandler.UPDATE_KEYSTORE_JOB_INTERVAL,
+ Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME);
+ long delay = mHandler.scheduleJobToUpdateAdbKeyStore();
+ if (Math.abs(delay - expectedValue) > epsilon) {
+ fail("The delay before the next scheduled job, " + delay
+ + ", is outside the expected value of " + expectedValue);
+ }
+
+ // Set the current expiration time to a minute from expiration and verify this new value is
+ // returned.
+ final long newExpirationTime = 60000;
+ mKeyStore.setLastConnectionTime(TEST_KEY_1,
+ System.currentTimeMillis() - Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME
+ + newExpirationTime, true);
+ expirationTime = mKeyStore.getNextExpirationTime();
+ if (Math.abs(expirationTime - newExpirationTime) > epsilon) {
+ fail("The expiration time for a key about to expire, " + expirationTime
+ + ", is outside the expected value of " + newExpirationTime);
+ }
+ delay = mHandler.scheduleJobToUpdateAdbKeyStore();
+ if (Math.abs(delay - newExpirationTime) > epsilon) {
+ fail("The delay before the next scheduled job, " + delay
+ + ", is outside the expected value of " + newExpirationTime);
+ }
+
+ // If a key is already expired the expiration time and delay before the next job runs should
+ // be 0.
+ mKeyStore.setLastConnectionTime(TEST_KEY_1, 1, true);
+ assertEquals("The expiration time for a key that is already expired must be 0", 0,
+ mKeyStore.getNextExpirationTime());
+ assertEquals(
+ "The delay before the next scheduled job for a key that is already expired must"
+ + " be 0", 0, mHandler.scheduleJobToUpdateAdbKeyStore());
+
+ // If the previous behavior of never removing old keys is set then the expiration time
+ // should be -1 to indicate the job does not need to run.
+ setAllowedConnectionTime(0);
+ assertEquals("The expiration time must be -1 when the keys are set to never expire", -1,
+ mKeyStore.getNextExpirationTime());
+ }
+
+ @Test
+ public void testConnectionTimeUpdatedWithConnectedKeyMessage() throws Exception {
+ // When a system successfully passes the SIGNATURE challenge adbd sends a connected key
+ // message to the framework to notify of the newly connected key. This message should
+ // trigger the AdbDebuggingManager to update the last connection time for this key and mark
+ // it as the currently connected key so that its time can be updated during subsequent
+ // keystore update jobs as well as when the disconnected message is received.
+
+ // Allow the test key to connect with the 'always allow' option selected.
+ runAdbTest(TEST_KEY_1, true, true, false);
+
+ // Simulate disconnecting the key before a subsequent connection without user interaction.
+ disconnectKey(TEST_KEY_1);
+
+ // Get the last connection time for the key to verify that it is updated when the connected
+ // key message is sent.
+ long connectionTime = mKeyStore.getLastConnectionTime(TEST_KEY_1);
+ Thread.sleep(10);
+ mHandler.obtainMessage(AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_CONNECTED_KEY,
+ TEST_KEY_1).sendToTarget();
+ flushHandlerQueue();
+ assertNotEquals(
+ "The connection time for the key must be updated when the connected key message "
+ + "is received",
+ connectionTime, mKeyStore.getLastConnectionTime(TEST_KEY_1));
+
+ // Verify that the scheduled job updates the connection time of the key.
+ connectionTime = mKeyStore.getLastConnectionTime(TEST_KEY_1);
+ Thread.sleep(10);
+ updateKeyStore();
+ assertNotEquals(
+ "The connection time for the key must be updated when the update keystore message"
+ + " is sent",
+ connectionTime, mKeyStore.getLastConnectionTime(TEST_KEY_1));
+
+ // Verify that the connection time is updated when the key is disconnected.
+ connectionTime = mKeyStore.getLastConnectionTime(TEST_KEY_1);
+ Thread.sleep(10);
+ disconnectKey(TEST_KEY_1);
+ assertNotEquals(
+ "The connection time for the key must be updated when the disconnected message is"
+ + " received",
+ connectionTime, mKeyStore.getLastConnectionTime(TEST_KEY_1));
+ }
+
+ @Test
+ public void testClearAuthorizations() throws Exception {
+ // When the user selects the 'Revoke USB debugging authorizations' all previously 'always
+ // allow' keys should be deleted.
+
+ // Set the allowed connection time to the default value to ensure tests do not fail due to
+ // a small value.
+ setAllowedConnectionTime(Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME);
+
+ // Allow the test key to connect with the 'always allow' option selected.
+ runAdbTest(TEST_KEY_1, true, true, false);
+ persistKeyStore();
+
+ // Verify that the key is authorized and in the adb_keys file
+ assertTrue(
+ "The test key must be in the keystore after the 'always allow' option is selected",
+ mKeyStore.isKeyAuthorized(TEST_KEY_1));
+ assertTrue(
+ "The test key must be in the adb_keys file after the 'always allow option is "
+ + "selected",
+ isKeyInFile(TEST_KEY_1, mAdbKeyFile));
+
+ // Send the message to clear the adb authorizations and verify that the keys are no longer
+ // authorized.
+ clearKeyStore();
+ assertFalse(
+ "The test key must not be in the keystore after clearing the authorizations",
+ mKeyStore.isKeyAuthorized(TEST_KEY_1));
+ assertFalse(
+ "The test key must not be in the adb_keys file after clearing the authorizations",
+ isKeyInFile(TEST_KEY_1, mAdbKeyFile));
+ }
+
+ @Test
+ public void testClearKeystoreAfterDisablingAdb() throws Exception {
+ // When the user disables adb they should still be able to clear the authorized keys.
+
+ // Allow the test key to connect with the 'always allow' option selected and persist the
+ // keystore.
+ runAdbTest(TEST_KEY_1, true, true, false);
+ persistKeyStore();
+
+ // Disable adb and verify that the keystore can be cleared without throwing an exception.
+ disableAdb();
+ clearKeyStore();
+ assertFalse(
+ "The test key must not be in the adb_keys file after clearing the authorizations",
+ isKeyInFile(TEST_KEY_1, mAdbKeyFile));
+ }
+
+ @Test
+ public void testUntrackedUserKeysAddedToKeystore() throws Exception {
+ // When a device is first updated to a build that tracks the connection time of adb keys
+ // the keys in the user key file will not have a connection time. To prevent immediately
+ // deleting keys that the user is actively using these untracked keys should be added to the
+ // keystore with the current system time; this gives the user time to reconnect
+ // automatically with an active key while inactive keys are deleted after the expiration
+ // time.
+
+ final long epsilon = 5000;
+ final String[] testKeys = {TEST_KEY_1, TEST_KEY_2};
+
+ // Add the test keys to the user key file.
+ FileOutputStream fo = new FileOutputStream(mAdbKeyFile);
+ for (String key : testKeys) {
+ fo.write(key.getBytes());
+ fo.write('\n');
+ }
+ fo.close();
+
+ // Set the expiration time to the default and use this value to verify the expiration time
+ // of the previously untracked keys.
+ setAllowedConnectionTime(Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME);
+
+ // The untracked keys should be added to the keystore as part of the constructor.
+ AdbDebuggingManager.AdbKeyStore adbKeyStore = mManager.new AdbKeyStore(mAdbKeyXmlFile);
+
+ // Verify that the connection time for each test key is within a small value of the current
+ // time.
+ long time = System.currentTimeMillis();
+ for (String key : testKeys) {
+ long connectionTime = adbKeyStore.getLastConnectionTime(key);
+ if (Math.abs(connectionTime - connectionTime) > epsilon) {
+ fail("The connection time for a previously untracked key, " + connectionTime
+ + ", is beyond the current time of " + time);
+ }
+ }
+ }
+
+ @Test
+ public void testConnectionTimeUpdatedForMultipleConnectedKeys() throws Exception {
+ // Since ADB supports multiple simultaneous connections verify that the connection time of
+ // each key is updated by the scheduled job as long as it is connected.
+
+ // Allow both test keys to connect with the 'always allow' option selected.
+ runAdbTest(TEST_KEY_1, true, true, false);
+ runAdbTest(TEST_KEY_2, true, true, false);
+
+ // Sleep a small amount of time to ensure the connection time is updated by the scheduled
+ // job.
+ long connectionTime1 = mKeyStore.getLastConnectionTime(TEST_KEY_1);
+ long connectionTime2 = mKeyStore.getLastConnectionTime(TEST_KEY_2);
+ Thread.sleep(10);
+ updateKeyStore();
+ assertNotEquals(
+ "The connection time for test key 1 must be updated after the scheduled job runs",
+ connectionTime1, mKeyStore.getLastConnectionTime(TEST_KEY_1));
+ assertNotEquals(
+ "The connection time for test key 2 must be updated after the scheduled job runs",
+ connectionTime2, mKeyStore.getLastConnectionTime(TEST_KEY_2));
+
+ // Disconnect the second test key and verify that the last connection time of the first key
+ // is the only one updated.
+ disconnectKey(TEST_KEY_2);
+ connectionTime1 = mKeyStore.getLastConnectionTime(TEST_KEY_1);
+ connectionTime2 = mKeyStore.getLastConnectionTime(TEST_KEY_2);
+ Thread.sleep(10);
+ updateKeyStore();
+ assertNotEquals(
+ "The connection time for test key 1 must be updated after another key is "
+ + "disconnected and the scheduled job runs",
+ connectionTime1, mKeyStore.getLastConnectionTime(TEST_KEY_1));
+ assertEquals(
+ "The connection time for test key 2 must not be updated after it is disconnected",
+ connectionTime2, mKeyStore.getLastConnectionTime(TEST_KEY_2));
+ }
+
/**
* Runs an adb test with the provided configuration.
*
@@ -440,10 +718,78 @@
allowKey ? RESPONSE_KEY_ALLOWED : RESPONSE_KEY_DENIED, threadResult.mMessage);
// if the key is not allowed or not always allowed verify it is not in the key store
if (!allowKey || !alwaysAllow) {
- assertFalse(
- "The key should not be allowed automatically on subsequent connection attempts",
+ assertFalse("The key must not be authorized in the key store",
mKeyStore.isKeyAuthorized(key));
+ assertFalse(
+ "The key must not be stored in the adb_keys file",
+ isKeyInFile(key, mAdbKeyFile));
}
+ flushHandlerQueue();
+ }
+
+ private void persistKeyStore() throws Exception {
+ // Send a message to the handler to persist the key store.
+ mHandler.obtainMessage(
+ AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_PERSIST_KEYSTORE)
+ .sendToTarget();
+ flushHandlerQueue();
+ }
+
+ private void disconnectKey(String key) throws Exception {
+ // Send a message to the handler to disconnect the currently connected key.
+ mHandler.obtainMessage(AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_DISCONNECT,
+ key).sendToTarget();
+ flushHandlerQueue();
+ }
+
+ private void updateKeyStore() throws Exception {
+ // Send a message to the handler to run the update keystore job.
+ mHandler.obtainMessage(
+ AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_UPDATE_KEYSTORE).sendToTarget();
+ flushHandlerQueue();
+ }
+
+ private void clearKeyStore() throws Exception {
+ // Send a message to the handler to clear all previously authorized keys.
+ mHandler.obtainMessage(
+ AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_CLEAR).sendToTarget();
+ flushHandlerQueue();
+ }
+
+ private void disableAdb() throws Exception {
+ // Send a message to the handler to disable adb.
+ mHandler.obtainMessage(
+ AdbDebuggingManager.AdbDebuggingHandler.MESSAGE_ADB_DISABLED).sendToTarget();
+ flushHandlerQueue();
+ }
+
+ private void flushHandlerQueue() throws Exception {
+ // Post a Runnable to ensure that all of the current messages in the queue are flushed.
+ CountDownLatch latch = new CountDownLatch(1);
+ mHandler.post(() -> {
+ latch.countDown();
+ });
+ if (!latch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
+ fail("The Runnable to flush the handler's queue did not complete within the timeout "
+ + "period");
+ }
+ }
+
+ private boolean isKeyInFile(String key, File keyFile) throws Exception {
+ if (key == null) {
+ return false;
+ }
+ if (keyFile.exists()) {
+ try (BufferedReader in = new BufferedReader(new FileReader(keyFile))) {
+ String currKey;
+ while ((currKey = in.readLine()) != null) {
+ if (key.equals(currKey)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java
index c42a718..d901179 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -29,25 +29,28 @@
import static com.google.common.truth.Truth.assertWithMessage;
import android.app.ActivityManager;
+import android.app.AppOpsManager;
import android.app.AppOpsManager.OpEntry;
import android.app.AppOpsManager.PackageOps;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
+import android.os.RemoteCallback;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.server.appop.AppOpsService;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Unit tests for AppOpsService. Covers functionality that is difficult to test using CTS tests
@@ -216,6 +219,45 @@
}
@Test
+ public void testPackageRemovedHistoricalOps() throws InterruptedException {
+ mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, mMyPackageName);
+
+ AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000);
+ historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, mMyPackageName,
+ AppOpsManager.UID_STATE_PERSISTENT, 0, 1);
+
+ mAppOpsService.addHistoricalOps(historicalOps);
+
+ AtomicReference<AppOpsManager.HistoricalOps> resultOpsRef = new AtomicReference<>();
+ AtomicReference<CountDownLatch> latchRef = new AtomicReference<>(new CountDownLatch(1));
+ RemoteCallback callback = new RemoteCallback(result -> {
+ resultOpsRef.set(result.getParcelable(AppOpsManager.KEY_HISTORICAL_OPS));
+ latchRef.get().countDown();
+ });
+
+ // First, do a fetch to ensure it's written
+ mAppOpsService.getHistoricalOps(mMyUid, mMyPackageName, null, 0, Long.MAX_VALUE, 0,
+ callback);
+
+ latchRef.get().await(5, TimeUnit.SECONDS);
+ assertThat(latchRef.get().getCount()).isEqualTo(0);
+ assertThat(resultOpsRef.get().isEmpty()).isFalse();
+
+ // Then, check it's deleted on removal
+ mAppOpsService.packageRemoved(mMyUid, mMyPackageName);
+
+ latchRef.set(new CountDownLatch(1));
+
+ mAppOpsService.getHistoricalOps(mMyUid, mMyPackageName, null, 0, Long.MAX_VALUE, 0,
+ callback);
+
+ latchRef.get().await(5, TimeUnit.SECONDS);
+ assertThat(latchRef.get().getCount()).isEqualTo(0);
+ assertThat(resultOpsRef.get().isEmpty()).isTrue();
+ }
+
+ @Test
public void testUidRemoved() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED);
mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, mMyPackageName);
diff --git a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
index de841a0..8bb8aae 100644
--- a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
@@ -1029,6 +1029,34 @@
assertDwbActive(true);
}
+ @Test
+ public void displayWhiteBalance_disabledWhileAccessibilityColorCorrectionEnabled() {
+ setDisplayWhiteBalanceEnabled(true);
+ startService();
+ setAccessibilityColorCorrection(true);
+
+ mCds.updateDisplayWhiteBalanceStatus();
+ assertDwbActive(false);
+
+ setAccessibilityColorCorrection(false);
+ mCds.updateDisplayWhiteBalanceStatus();
+ assertDwbActive(true);
+ }
+
+ @Test
+ public void displayWhiteBalance_disabledWhileAccessibilityColorInversionEnabled() {
+ setDisplayWhiteBalanceEnabled(true);
+ startService();
+ setAccessibilityColorInversion(true);
+
+ mCds.updateDisplayWhiteBalanceStatus();
+ assertDwbActive(false);
+
+ setAccessibilityColorInversion(false);
+ mCds.updateDisplayWhiteBalanceStatus();
+ assertDwbActive(true);
+ }
+
/**
* Configures Night display to use a custom schedule.
*
diff --git a/services/tests/servicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java b/services/tests/servicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java
index 1dd4e15..4ef156e 100644
--- a/services/tests/servicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java
@@ -18,6 +18,11 @@
import static com.google.common.truth.Truth.assertWithMessage;
+import androidx.test.InstrumentationRegistry;
+
+import java.lang.System;
+import java.util.Arrays;
+
import org.junit.Before;
import org.junit.Test;
@@ -28,6 +33,8 @@
@Before
public void setUp() {
mDisplayWhiteBalanceTintController = new DisplayWhiteBalanceTintController();
+ mDisplayWhiteBalanceTintController.setUp(InstrumentationRegistry.getContext(), true);
+ mDisplayWhiteBalanceTintController.setActivated(true);
}
@Test
@@ -59,4 +66,31 @@
.isEqualTo(colorTemperature);
}
+ @Test
+ public void displayWhiteBalance_setMatrixValidDwbCalculation() {
+ float[] currentMatrix = mDisplayWhiteBalanceTintController.getMatrix();
+ float[] oldMatrix = Arrays.copyOf(currentMatrix, currentMatrix.length);
+
+ mDisplayWhiteBalanceTintController
+ .setMatrix(mDisplayWhiteBalanceTintController.mCurrentColorTemperature + 1);
+ assertWithMessage("DWB matrix did not change when setting a new temperature")
+ .that(Arrays.equals(oldMatrix, currentMatrix))
+ .isFalse();
+ }
+
+ @Test
+ public void displayWhiteBalance_setMatrixInvalidDwbCalculation() {
+ Arrays.fill(mDisplayWhiteBalanceTintController.mDisplayNominalWhiteXYZ, 0);
+ mDisplayWhiteBalanceTintController
+ .setMatrix(mDisplayWhiteBalanceTintController.mCurrentColorTemperature + 1);
+ assertWithMessage("DWB matrix not set to identity after an invalid DWB calculation")
+ .that(Arrays.equals(mDisplayWhiteBalanceTintController.getMatrix(),
+ new float[] {
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+ })
+ ).isTrue();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientFilterTest.java b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientFilterTest.java
new file mode 100644
index 0000000..7816493
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientFilterTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.whitebalance;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.ContextWrapper;
+import android.content.res.Resources;
+import android.util.TypedValue;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class AmbientFilterTest {
+ private ContextWrapper mContextSpy;
+ private Resources mResourcesSpy;
+
+ @Before
+ public void setUp() throws Exception {
+ mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
+ mResourcesSpy = spy(mContextSpy.getResources());
+ when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
+ }
+
+ @Test
+ public void testBrightnessFilter_ZeroIntercept() throws Exception {
+ final int horizon = 5 * 1000;
+ final int time_start = 30 * 1000;
+ final float intercept = 0.0f;
+ final int prediction_time = 100; // Hardcoded in AmbientFilter: prediction of how long the
+ // latest prediction will last before a new prediction.
+ setMockValues(mResourcesSpy, horizon, intercept);
+ AmbientFilter filter = DisplayWhiteBalanceFactory.createBrightnessFilter(mResourcesSpy);
+
+ // Add first value and verify
+ filter.addValue(time_start, 30);
+ assertEquals(30, filter.getEstimate(time_start + prediction_time), 0.001);
+
+ // Add second value and verify that they are being averaged:
+ filter.addValue(time_start + prediction_time, 40);
+ // We check immediately after the value is added to verify that the weight of the
+ // prediction time is being correctly applied to the recent value correctly.
+ // In this case (time is in seconds so 100ms = 0.1s):
+ // weight 1 (w1) = (0.5*0.1^2 - 0.5*0^2) = 0.005
+ // weight 2 (w2) = (0.5*0.2^2 - 0.5*0.1^2) = 0.015
+ // w_t = w1 + w2 = 0.02
+ // total = w1 * 30 + w2 * 40 = 0.75
+ // estimate = total / w_t = 0.75 / 0.02 = 37.5
+ assertEquals(37.5, filter.getEstimate(time_start + prediction_time), 0.001);
+
+ // Add a third value to push the first value off of the buffer.
+ filter.addValue(time_start + horizon + prediction_time, 50);
+ assertEquals(40.38846f, filter.getEstimate(time_start + horizon + prediction_time), 0.001);
+ }
+
+ @Test
+ public void testBrightnessFilter_WithIntercept() throws Exception {
+ final int horizon = 5 * 1000;
+ final int time_start = 30 * 1000;
+ final float intercept = 10f;
+ final int prediction_time = 100;
+
+ setMockValues(mResourcesSpy, horizon, intercept);
+ AmbientFilter filter = DisplayWhiteBalanceFactory.createBrightnessFilter(mResourcesSpy);
+
+ // Add first value and verify
+ filter.addValue(time_start, 30);
+ assertEquals(30, filter.getEstimate(time_start + prediction_time), 0.001);
+
+ // Add second value and verify that they are being averaged:
+ filter.addValue(time_start + prediction_time, 40);
+ // We check immediately after the value is added to verify that the weight of the
+ // prediction time is being correctly applied to the recent value correctly.
+ // In this case (time is in seconds so 100ms = 0.1s):
+ // weight 1 (w1) = (0.5*0.1^2 + 0.1*100) - (0.5*0^2 + 0*100) = 1.005
+ // weight 2 (w2) = (0.5*0.2^2 + 0.2*100) - (0.5*0.1^2 + 0.1*100) = 1.015
+ // w_t = w1 + w2 = 2.02
+ // total = w1 * 30 + w2 * 40 = 70.75
+ // estimate = total / w_t = 70.75 / 2.02 = 35.024752475
+ assertEquals(35.02475f, filter.getEstimate(time_start + prediction_time), 0.001);
+
+ // Add a third value to push the first value off of the buffer.
+ filter.addValue(time_start + horizon + prediction_time, 50);
+ assertEquals(40.23513f, filter.getEstimate(time_start + horizon + prediction_time), 0.001);
+ }
+
+ private void setMockValues(Resources resources, int horizon, float intercept) {
+ doAnswer(invocation -> {
+ TypedValue value = (TypedValue) invocation.getArguments()[1];
+ value.type = TypedValue.TYPE_FLOAT;
+ value.data = Float.floatToRawIntBits(intercept);
+ return null;
+ }).when(mResourcesSpy).getValue(
+ eq(com.android.internal.R.dimen
+ .config_displayWhiteBalanceBrightnessFilterIntercept),
+ any(TypedValue.class), eq(true));
+ when(mResourcesSpy.getInteger(
+ com.android.internal.R.integer
+ .config_displayWhiteBalanceBrightnessFilterHorizon)).thenReturn(horizon);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientSensorTest.java b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientSensorTest.java
new file mode 100644
index 0000000..6ff4f3b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientSensorTest.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2019 The Android Open 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.whitebalance;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContextWrapper;
+import android.content.res.Resources;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.server.display.whitebalance.AmbientSensor.AmbientBrightnessSensor;
+import com.android.server.display.whitebalance.AmbientSensor.AmbientColorTemperatureSensor;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(JUnit4.class)
+public final class AmbientSensorTest {
+ private static final int AMBIENT_COLOR_TYPE = 20705;
+ private static final String AMBIENT_COLOR_TYPE_STR = "colorSensoryDensoryDoc";
+
+ private Handler mHandler = new Handler(Looper.getMainLooper());
+ private Sensor mLightSensor;
+ private Sensor mAmbientColorSensor;
+ private ContextWrapper mContextSpy;
+ private Resources mResourcesSpy;
+
+ @Mock private SensorManager mSensorManagerMock;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mLightSensor = createSensor(Sensor.TYPE_LIGHT, null);
+ mAmbientColorSensor = createSensor(AMBIENT_COLOR_TYPE, AMBIENT_COLOR_TYPE_STR);
+ mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
+ mResourcesSpy = spy(mContextSpy.getResources());
+ when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
+ }
+
+ @Test
+ public void testAmbientBrightnessSensorCallback_NoCallbacks() throws Exception {
+ when(mSensorManagerMock.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(mLightSensor);
+ AmbientBrightnessSensor abs = DisplayWhiteBalanceFactory.createBrightnessSensor(
+ mHandler, mSensorManagerMock, InstrumentationRegistry.getContext().getResources());
+
+ abs.setCallbacks(null);
+ abs.setEnabled(true);
+ ArgumentCaptor<SensorEventListener> captor =
+ ArgumentCaptor.forClass(SensorEventListener.class);
+ verify(mSensorManagerMock).registerListener(captor.capture(), isA(Sensor.class), anyInt(),
+ isA(Handler.class));
+
+ // There should be no issues when we callback the listener, even if there is no callback
+ // set.
+ SensorEventListener listener = captor.getValue();
+ listener.onSensorChanged(createSensorEvent(mLightSensor, 100));
+ }
+
+ @Test
+ public void testAmbientBrightnessSensorCallback_CallbacksCalled() throws Exception {
+ final int luxValue = 83;
+ when(mSensorManagerMock.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(mLightSensor);
+ AmbientBrightnessSensor abs = DisplayWhiteBalanceFactory.createBrightnessSensor(
+ mHandler, mSensorManagerMock, InstrumentationRegistry.getContext().getResources());
+
+ final int[] luxReturned = new int[] { -1 };
+ final CountDownLatch changeSignal = new CountDownLatch(1);
+ abs.setCallbacks(new AmbientBrightnessSensor.Callbacks() {
+ @Override
+ public void onAmbientBrightnessChanged(float value) {
+ luxReturned[0] = (int) value;
+ changeSignal.countDown();
+ }
+ });
+
+ abs.setEnabled(true);
+ ArgumentCaptor<SensorEventListener> captor =
+ ArgumentCaptor.forClass(SensorEventListener.class);
+ verify(mSensorManagerMock).registerListener(captor.capture(), eq(mLightSensor),
+ anyInt(), eq(mHandler));
+ SensorEventListener listener = captor.getValue();
+ listener.onSensorChanged(createSensorEvent(mLightSensor, luxValue));
+ assertTrue(changeSignal.await(5, TimeUnit.SECONDS));
+ assertEquals(luxValue, luxReturned[0]);
+ }
+
+ @Test
+ public void testAmbientColorTemperatureSensorCallback_CallbacksCalled() throws Exception {
+ final int colorTempValue = 79;
+ final List<Sensor> sensorList = ImmutableList.of(mLightSensor, mAmbientColorSensor);
+ when(mSensorManagerMock.getSensorList(Sensor.TYPE_ALL)).thenReturn(sensorList);
+ when(mResourcesSpy.getString(
+ com.android.internal.R.string.config_displayWhiteBalanceColorTemperatureSensorName))
+ .thenReturn(AMBIENT_COLOR_TYPE_STR);
+
+ AmbientColorTemperatureSensor abs = DisplayWhiteBalanceFactory.createColorTemperatureSensor(
+ mHandler, mSensorManagerMock, mResourcesSpy);
+
+ final int[] colorTempReturned = new int[] { -1 };
+ final CountDownLatch changeSignal = new CountDownLatch(1);
+ abs.setCallbacks(new AmbientColorTemperatureSensor.Callbacks() {
+ @Override
+ public void onAmbientColorTemperatureChanged(float value) {
+ colorTempReturned[0] = (int) value;
+ changeSignal.countDown();
+ }
+ });
+
+ abs.setEnabled(true);
+ ArgumentCaptor<SensorEventListener> captor =
+ ArgumentCaptor.forClass(SensorEventListener.class);
+ verify(mSensorManagerMock).registerListener(captor.capture(), eq(mAmbientColorSensor),
+ anyInt(), eq(mHandler));
+ SensorEventListener listener = captor.getValue();
+ listener.onSensorChanged(createSensorEvent(mAmbientColorSensor, colorTempValue));
+ assertTrue(changeSignal.await(5, TimeUnit.SECONDS));
+ assertEquals(colorTempValue, colorTempReturned[0]);
+ }
+
+ private SensorEvent createSensorEvent(Sensor sensor, int lux) throws Exception {
+ final Constructor<SensorEvent> constructor =
+ SensorEvent.class.getDeclaredConstructor(int.class);
+ constructor.setAccessible(true);
+ final SensorEvent event = constructor.newInstance(1);
+ event.sensor = sensor;
+ event.values[0] = lux;
+ event.timestamp = SystemClock.elapsedRealtimeNanos();
+ return event;
+ }
+
+
+ private void setSensorType(Sensor sensor, int type, String strType) throws Exception {
+ Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE);
+ setter.setAccessible(true);
+ setter.invoke(sensor, type);
+ if (strType != null) {
+ Field f = sensor.getClass().getDeclaredField("mStringType");
+ f.setAccessible(true);
+ f.set(sensor, strType);
+ }
+ }
+
+ private Sensor createSensor(int type, String strType) throws Exception {
+ Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
+ constr.setAccessible(true);
+ Sensor sensor = constr.newInstance();
+ setSensorType(sensor, type, strType);
+ return sensor;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 10fb3ba..19ed5f3 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -110,7 +110,7 @@
}
@Override
- public boolean hasBiometrics() {
+ public boolean hasEnrolledBiometrics() {
return false;
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
index 8af4edd..18453aa 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -27,6 +27,7 @@
import android.content.pm.UserInfo;
import android.database.sqlite.SQLiteDatabase;
import android.os.FileUtils;
+import android.os.SystemClock;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.platform.test.annotations.Presubmit;
@@ -125,7 +126,7 @@
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 100; i++) {
final int threadId = i;
- threads.add(new Thread() {
+ threads.add(new Thread("testKeyValue_Concurrency_" + i) {
@Override
public void run() {
synchronized (monitor) {
@@ -134,17 +135,17 @@
} catch (InterruptedException e) {
return;
}
- mStorage.writeKeyValue("key", "1 from thread " + threadId, 0);
- mStorage.readKeyValue("key", "default", 0);
- mStorage.writeKeyValue("key", "2 from thread " + threadId, 0);
- mStorage.readKeyValue("key", "default", 0);
- mStorage.writeKeyValue("key", "3 from thread " + threadId, 0);
- mStorage.readKeyValue("key", "default", 0);
- mStorage.writeKeyValue("key", "4 from thread " + threadId, 0);
- mStorage.readKeyValue("key", "default", 0);
- mStorage.writeKeyValue("key", "5 from thread " + threadId, 0);
- mStorage.readKeyValue("key", "default", 0);
}
+ mStorage.writeKeyValue("key", "1 from thread " + threadId, 0);
+ mStorage.readKeyValue("key", "default", 0);
+ mStorage.writeKeyValue("key", "2 from thread " + threadId, 0);
+ mStorage.readKeyValue("key", "default", 0);
+ mStorage.writeKeyValue("key", "3 from thread " + threadId, 0);
+ mStorage.readKeyValue("key", "default", 0);
+ mStorage.writeKeyValue("key", "4 from thread " + threadId, 0);
+ mStorage.readKeyValue("key", "default", 0);
+ mStorage.writeKeyValue("key", "5 from thread " + threadId, 0);
+ mStorage.readKeyValue("key", "default", 0);
}
});
threads.get(i).start();
@@ -153,12 +154,7 @@
synchronized (monitor) {
monitor.notifyAll();
}
- for (int i = 0; i < threads.size(); i++) {
- try {
- threads.get(i).join();
- } catch (InterruptedException e) {
- }
- }
+ joinAll(threads, 10000);
assertEquals('5', mStorage.readKeyValue("key", "default", 0).charAt(0));
mStorage.clearCache();
assertEquals('5', mStorage.readKeyValue("key", "default", 0).charAt(0));
@@ -515,4 +511,29 @@
}
return captured[0];
}
+
+ private static void joinAll(List<Thread> threads, long timeoutMillis) {
+ long deadline = SystemClock.uptimeMillis() + timeoutMillis;
+ for (Thread t : threads) {
+ try {
+ t.join(deadline - SystemClock.uptimeMillis());
+ if (t.isAlive()) {
+ t.interrupt();
+ throw new RuntimeException(
+ "Joining " + t + " timed out. Stack: \n" + getStack(t));
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while joining " + t, e);
+ }
+ }
+ }
+
+ private static String getStack(Thread t) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(t.toString()).append('\n');
+ for (StackTraceElement ste : t.getStackTrace()) {
+ sb.append("\tat ").append(ste.toString()).append('\n');
+ }
+ return sb.toString();
+ }
}
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 6845f15..b806180 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -1584,6 +1584,22 @@
}
/**
+ * Make a shortcut with an ID and Category.
+ */
+ protected ShortcutInfo makeShortcutWithCategory(String id, Set<String> categories) {
+ final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id)
+ .setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
+ .setShortLabel("title-" + id)
+ .setIntent(makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class))
+ .setCategories(categories);
+ final ShortcutInfo s = b.build();
+
+ s.setTimestamp(mInjectedCurrentTimeMillis); // HACK
+
+ return s;
+ }
+
+ /**
* Make an intent.
*/
protected Intent makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues) {
@@ -1818,6 +1834,17 @@
}
/**
+ * @return the number of shortcuts stored internally for the caller that can be used as a share
+ * target in the ShareSheet. Such shortcuts have a matching category with at least one of the
+ * defined ShareTargets from the app's Xml resource.
+ */
+ protected int getCallerSharingShortcutCount() {
+ final ShortcutPackage p = mService.getPackageShortcutForTest(
+ getCallingPackage(), getCallingUserId());
+ return p == null ? 0 : p.getSharingShortcutCount();
+ }
+
+ /**
* @return all shortcuts owned by caller that are actually visible via ShortcutManager.
* See also {@link #getCallerShortcuts}.
*/
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
index eb4db7a..ba26f79 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
@@ -17,6 +17,7 @@
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set;
import android.content.ComponentName;
import android.content.pm.ShortcutInfo;
@@ -25,6 +26,8 @@
import com.android.frameworks.servicestests.R;
import com.android.server.pm.ShortcutService.ConfigConstants;
+import java.util.Set;
+
/**
* Tests related to shortcut rank auto-adjustment.
*/
@@ -50,6 +53,10 @@
return makeShortcutWithActivityAndRank(id, activity, ShortcutInfo.RANK_NOT_SET);
}
+ private ShortcutInfo shortcut(String id, Set<String> categories) {
+ return makeShortcutWithCategory(id, categories);
+ }
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -502,4 +509,30 @@
runTestWithManifestShortcuts(() -> testDisableShortcuts_noManifestShortcuts());
}
+ public void testGetSharingShortcutCount() {
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_share_targets);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+ // There are two valid <share-target> definitions in the test manifest with two different
+ // categories: {"com.test.category.CATEGORY1", "com.test.category.CATEGORY2"} and
+ // {"com.test.category.CATEGORY5", "com.test.category.CATEGORY6"}.
+ //
+ // Note that a shortcut is a match, only if it has ALL of the categories of at least one
+ // of the share-target definitions from the manifest.
+
+ mManager.addDynamicShortcuts(list(
+ shortcut("s1", set("com.test.category.CATEGORY1", "com.test.category.CATEGORY2")),
+ shortcut("s2", set("com.test.category.CATEGORY5")),
+ shortcut("s3", set("com.test.category.CATEGORY5", "com.test.category.CATEGORY6")),
+ shortcut("s4", set("com.test.category.CATEGORY1", "com.test.category.CATEGORY2",
+ "com.test.category.CATEGORY5", "com.test.category.CATEGORY6")),
+ shortcut("s5", A1)
+ ));
+
+ assertEquals(3, getCallerSharingShortcutCount());
+ }
}
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 c6be1c0..d5d32bd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
@@ -509,25 +509,17 @@
}
@Test
- public void testCannotSuspendWhenProfileOwner() throws IOException {
+ public void testCanSuspendWhenProfileOwner() throws IOException {
assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
assertTrue("Profile-owner could not be set", setProfileOwner());
- try {
- suspendTestPackage(null, null, null);
- fail("Suspend succeeded. Expected UnsupportedOperationException");
- } catch (UnsupportedOperationException uex) {
- }
+ suspendTestPackage(null, null, null);
}
@Test
- public void testCannotSuspendWhenDeviceOwner() throws IOException {
+ public void testCanSuspendWhenDeviceOwner() throws IOException {
assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
assertTrue("Device-owner could not be set", setDeviceOwner());
- try {
- suspendTestPackage(null, null, null);
- fail("Suspend succeeded. Expected UnsupportedOperationException");
- } catch (UnsupportedOperationException uex) {
- }
+ suspendTestPackage(null, null, null);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
index c30a7dd..a63f49b 100644
--- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.atMost;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -182,10 +183,22 @@
}
@Test
+ public void testOnUserActivity_ignoresIfAlreadyDoneForThatNextScreenDimming() {
+ long when = registerAttention();
+ verify(mAttentionManagerInternal).checkAttention(anyLong(), any());
+ assertThat(when).isLessThan(mNextDimming);
+ clearInvocations(mAttentionManagerInternal);
+
+ long redundantWhen = mAttentionDetector.updateUserActivity(mNextDimming);
+ assertThat(redundantWhen).isEqualTo(mNextDimming);
+ verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
+ }
+
+ @Test
public void testOnUserActivity_skipsIfAlreadyScheduled() {
registerAttention();
reset(mAttentionManagerInternal);
- long when = mAttentionDetector.updateUserActivity(mNextDimming);
+ long when = mAttentionDetector.updateUserActivity(mNextDimming + 1);
verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
assertThat(when).isLessThan(mNextDimming);
}
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index e74b959..c55f459 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -223,6 +223,22 @@
config9.densityDpi = 19;
mIntervalStats.getOrCreateConfigurationStats(config9);
+ Configuration config10 = new Configuration();
+ final Locale locale10 = new Locale.Builder()
+ .setLocale(new Locale("zh", "CN"))
+ .setScript("Hans")
+ .build();
+ config10.setLocale(locale10);
+ mIntervalStats.getOrCreateConfigurationStats(config10);
+
+ Configuration config11 = new Configuration();
+ final Locale locale11 = new Locale.Builder()
+ .setLocale(new Locale("zh", "CN"))
+ .setScript("Hant")
+ .build();
+ config11.setLocale(locale11);
+ mIntervalStats.getOrCreateConfigurationStats(config11);
+
mIntervalStats.activeConfiguration = config9;
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 8d56bc4..d2332bf 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3026,104 +3026,6 @@
}
@Test
- public void testRecents() throws Exception {
- Set<NotifyingApp> expected = new HashSet<>();
-
- final NotificationRecord oldest = new NotificationRecord(mContext,
- generateSbn("p", 1000, 9, 0), mTestNotificationChannel);
- mService.logRecentLocked(oldest);
- for (int i = 1; i <= 5; i++) {
- NotificationRecord r = new NotificationRecord(mContext,
- generateSbn("p" + i, i, i*100, 0), mTestNotificationChannel);
- expected.add(new NotifyingApp()
- .setPackage(r.sbn.getPackageName())
- .setUid(r.sbn.getUid())
- .setLastNotified(r.sbn.getPostTime()));
- mService.logRecentLocked(r);
- }
-
- List<NotifyingApp> apps = mBinderService.getRecentNotifyingAppsForUser(0).getList();
- assertTrue(apps.size() == 5);
- for (NotifyingApp actual : apps) {
- assertTrue("got unexpected result: " + actual, expected.contains(actual));
- }
- }
-
- @Test
- public void testRecentsNoDuplicatePackages() throws Exception {
- final NotificationRecord p1 = new NotificationRecord(mContext, generateSbn("p", 1, 1000, 0),
- mTestNotificationChannel);
- final NotificationRecord p2 = new NotificationRecord(mContext, generateSbn("p", 1, 2000, 0),
- mTestNotificationChannel);
-
- mService.logRecentLocked(p1);
- mService.logRecentLocked(p2);
-
- List<NotifyingApp> apps = mBinderService.getRecentNotifyingAppsForUser(0).getList();
- assertTrue(apps.size() == 1);
- NotifyingApp expected = new NotifyingApp().setPackage("p").setUid(1).setLastNotified(2000);
- assertEquals(expected, apps.get(0));
- }
-
- @Test
- public void testRecentsWithDuplicatePackage() throws Exception {
- Set<NotifyingApp> expected = new HashSet<>();
-
- final NotificationRecord oldest = new NotificationRecord(mContext,
- generateSbn("p", 1000, 9, 0), mTestNotificationChannel);
- mService.logRecentLocked(oldest);
- for (int i = 1; i <= 5; i++) {
- NotificationRecord r = new NotificationRecord(mContext,
- generateSbn("p" + i, i, i*100, 0), mTestNotificationChannel);
- expected.add(new NotifyingApp()
- .setPackage(r.sbn.getPackageName())
- .setUid(r.sbn.getUid())
- .setLastNotified(r.sbn.getPostTime()));
- mService.logRecentLocked(r);
- }
- NotificationRecord r = new NotificationRecord(mContext,
- generateSbn("p" + 3, 3, 300000, 0), mTestNotificationChannel);
- expected.remove(new NotifyingApp()
- .setPackage(r.sbn.getPackageName())
- .setUid(3)
- .setLastNotified(300));
- NotifyingApp newest = new NotifyingApp()
- .setPackage(r.sbn.getPackageName())
- .setUid(r.sbn.getUid())
- .setLastNotified(r.sbn.getPostTime());
- expected.add(newest);
- mService.logRecentLocked(r);
-
- List<NotifyingApp> apps = mBinderService.getRecentNotifyingAppsForUser(0).getList();
- assertTrue(apps.size() == 5);
- for (NotifyingApp actual : apps) {
- assertTrue("got unexpected result: " + actual, expected.contains(actual));
- }
- assertEquals(newest, apps.get(0));
- }
-
- @Test
- public void testRecentsMultiuser() throws Exception {
- final NotificationRecord user1 = new NotificationRecord(mContext,
- generateSbn("p", 1000, 9, 1), mTestNotificationChannel);
- mService.logRecentLocked(user1);
-
- final NotificationRecord user2 = new NotificationRecord(mContext,
- generateSbn("p2", 100000, 9999, 2), mTestNotificationChannel);
- mService.logRecentLocked(user2);
-
- assertEquals(0, mBinderService.getRecentNotifyingAppsForUser(0).getList().size());
- assertEquals(1, mBinderService.getRecentNotifyingAppsForUser(1).getList().size());
- assertEquals(1, mBinderService.getRecentNotifyingAppsForUser(2).getList().size());
-
- assertTrue(mBinderService.getRecentNotifyingAppsForUser(2).getList().contains(
- new NotifyingApp()
- .setPackage(user2.sbn.getPackageName())
- .setUid(user2.sbn.getUid())
- .setLastNotified(user2.sbn.getPostTime())));
- }
-
- @Test
public void testRestore() throws Exception {
int systemChecks = mService.countSystemChecks;
mBinderService.applyRestore(null, UserHandle.USER_SYSTEM);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotifyingAppTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotifyingAppTest.java
index 25e10d0..0c62831 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotifyingAppTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotifyingAppTest.java
@@ -36,7 +36,7 @@
@Test
public void testConstructor() {
NotifyingApp na = new NotifyingApp();
- assertEquals(0, na.getUid());
+ assertEquals(0, na.getUserId());
assertEquals(0, na.getLastNotified());
assertEquals(null, na.getPackage());
}
@@ -49,10 +49,10 @@
}
@Test
- public void testUid() {
+ public void testUserId() {
NotifyingApp na = new NotifyingApp();
- na.setUid(90);
- assertEquals(90, na.getUid());
+ na.setUserId(90);
+ assertEquals(90, na.getUserId());
}
@Test
@@ -66,7 +66,7 @@
public void testWriteToParcel() {
NotifyingApp na = new NotifyingApp();
na.setPackage("package");
- na.setUid(200);
+ na.setUserId(200);
na.setLastNotified(4000);
Parcel parcel = Parcel.obtain();
@@ -75,19 +75,19 @@
NotifyingApp na1 = NotifyingApp.CREATOR.createFromParcel(parcel);
assertEquals(na.getLastNotified(), na1.getLastNotified());
assertEquals(na.getPackage(), na1.getPackage());
- assertEquals(na.getUid(), na1.getUid());
+ assertEquals(na.getUserId(), na1.getUserId());
}
@Test
public void testCompareTo() {
NotifyingApp na1 = new NotifyingApp();
na1.setPackage("pkg1");
- na1.setUid(1000);
+ na1.setUserId(1000);
na1.setLastNotified(6);
NotifyingApp na2 = new NotifyingApp();
na2.setPackage("a");
- na2.setUid(999);
+ na2.setUserId(999);
na2.setLastNotified(1);
assertTrue(na1.compareTo(na2) < 0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index dc8b885..11a177a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -56,9 +56,14 @@
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.util.MergedConfiguration;
import android.util.MutableBoolean;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.IRemoteAnimationRunner.Stub;
+import android.view.RemoteAnimationAdapter;
+import android.view.RemoteAnimationTarget;
import androidx.test.filters.MediumTest;
@@ -568,6 +573,31 @@
eq(mActivity.app.mName), eq(mActivity.app.mUid), anyString());
}
+ @Test
+ public void testTakeOptions() {
+ ActivityOptions opts = ActivityOptions.makeRemoteAnimation(
+ new RemoteAnimationAdapter(new Stub() {
+
+ @Override
+ public void onAnimationStart(RemoteAnimationTarget[] apps,
+ IRemoteAnimationFinishedCallback finishedCallback) {
+
+ }
+
+ @Override
+ public void onAnimationCancelled() {
+
+ }
+ }, 0, 0));
+ mActivity.updateOptionsLocked(opts);
+ assertNotNull(mActivity.takeOptionsLocked(true /* fromClient */));
+ assertNotNull(mActivity.pendingOptions);
+
+ mActivity.updateOptionsLocked(ActivityOptions.makeBasic());
+ assertNotNull(mActivity.takeOptionsLocked(false /* fromClient */));
+ assertNull(mActivity.pendingOptions);
+ }
+
/** Setup {@link #mActivity} as a size-compat-mode-able activity without fixed orientation. */
private void prepareFixedAspectRatioUnresizableActivity() {
setupDisplayContentForCompatDisplayInsets();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 09b511a..53b0add 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -35,6 +35,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
@@ -71,6 +72,7 @@
import com.android.server.am.PendingIntentController;
import com.android.server.appop.AppOpsService;
import com.android.server.firewall.IntentFirewall;
+import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.TaskRecord.TaskRecordFactory;
import com.android.server.wm.utils.MockTracker;
@@ -132,6 +134,9 @@
mService.setWindowManager(null);
mService = null;
}
+ if (sMockWindowManagerService != null) {
+ reset(sMockWindowManagerService);
+ }
mMockTracker.close();
mMockTracker = null;
@@ -422,6 +427,7 @@
protected class TestActivityTaskManagerService extends ActivityTaskManagerService {
private PackageManagerInternal mPmInternal;
+ private PermissionPolicyInternal mPermissionPolicyInternal;
// ActivityStackSupervisor may be created more than once while setting up AMS and ATMS.
// We keep the reference in order to prevent creating it twice.
@@ -537,6 +543,16 @@
}
return mPmInternal;
}
+
+ @Override
+ PermissionPolicyInternal getPermissionPolicyInternal() {
+ if (mPermissionPolicyInternal == null) {
+ mPermissionPolicyInternal = mock(PermissionPolicyInternal.class);
+ doReturn(true).when(mPermissionPolicyInternal).checkStartActivity(any(), anyInt(),
+ any());
+ }
+ return mPermissionPolicyInternal;
+ }
}
private static class TestInjector extends ActivityManagerService.Injector {
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 777e4f4..035568f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -158,4 +158,22 @@
waitUntilHandlersIdle();
mToken.removeImmediately();
}
+
+ @Test
+ public void testCancelPendingChangeOnHide() {
+ // setup currently defaults to no snapshot.
+ setUpOnDisplay(mDisplayContent);
+
+ mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ assertEquals(1, mDisplayContent.mChangingApps.size());
+ assertTrue(mToken.isInChangeTransition());
+
+ // Changing visibility should cancel the change transition and become closing
+ mToken.setVisibility(false, false);
+ assertEquals(0, mDisplayContent.mChangingApps.size());
+ assertFalse(mToken.isInChangeTransition());
+
+ waitUntilHandlersIdle();
+ mToken.removeImmediately();
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 2d1dd39..20379a2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -105,6 +105,7 @@
}
@Test
+ @FlakyTest(bugId = 131005232)
public void testTransitWithinTask() {
synchronized (mWm.mGlobalLock) {
final AppWindowToken opening = createAppWindowToken(mDisplayContent,
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 9cdea9a..5a72a58 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -18,30 +18,40 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.graphics.Rect;
+import android.os.IBinder;
+import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
-
-import org.junit.Before;
-import org.junit.Test;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.IRemoteAnimationRunner;
+import android.view.RemoteAnimationAdapter;
+import android.view.RemoteAnimationTarget;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
+import org.junit.Before;
+import org.junit.Test;
+
/**
* Test class for {@link AppTransition}.
*
@@ -51,7 +61,6 @@
@SmallTest
@Presubmit
public class AppTransitionTests extends WindowTestsBase {
-
private DisplayContent mDc;
@Before
@@ -65,6 +74,7 @@
}
@Test
+ @FlakyTest(bugId = 131005232)
public void testKeyguardOverride() {
mWm.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false /* alwaysKeepCurrent */);
mWm.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
@@ -72,6 +82,7 @@
}
@Test
+ @FlakyTest(bugId = 131005232)
public void testKeyguardKeep() {
mWm.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
mWm.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false /* alwaysKeepCurrent */);
@@ -172,10 +183,62 @@
}
@Test
+ @FlakyTest(bugId = 131005232)
public void testLoadAnimationSafely() {
DisplayContent dc = createNewDisplay(Display.STATE_ON);
assertNull(dc.mAppTransition.loadAnimationSafely(
getInstrumentation().getTargetContext(), -1));
}
+ @Test
+ public void testCancelRemoteAnimationWhenFreeze() {
+ final DisplayContent dc = createNewDisplay(Display.STATE_ON);
+ final WindowState exitingAppWindow = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
+ dc, "exiting app");
+ final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
+ // Wait until everything in animation handler get executed to prevent the exiting window
+ // from being removed during WindowSurfacePlacer Traversal.
+ waitUntilHandlersIdle();
+
+ // Set a remote animator.
+ final TestRemoteAnimationRunner runner = new TestRemoteAnimationRunner();
+ final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
+ runner, 100, 50, true /* changeNeedsSnapshot */);
+ // RemoteAnimationController will tracking RemoteAnimationAdapter's caller with calling pid.
+ adapter.setCallingPid(123);
+
+ // Simulate activity finish flows to prepare app transition & set visibility,
+ // make sure transition is set as expected.
+ dc.prepareAppTransition(TRANSIT_ACTIVITY_CLOSE,
+ false /* alwaysKeepCurrent */, 0 /* flags */, false /* forceOverride */);
+ assertEquals(TRANSIT_ACTIVITY_CLOSE, dc.mAppTransition.getAppTransition());
+ dc.mAppTransition.overridePendingAppTransitionRemote(adapter);
+ exitingAppToken.setVisibility(false, false);
+ assertTrue(dc.mClosingApps.size() > 0);
+
+ // Make sure window is in animating stage before freeze, and cancel after freeze.
+ assertTrue(dc.isAppAnimating());
+ assertFalse(runner.mCancelled);
+ dc.mAppTransition.freeze();
+ assertFalse(dc.isAppAnimating());
+ assertTrue(runner.mCancelled);
+ }
+
+ private class TestRemoteAnimationRunner implements IRemoteAnimationRunner {
+ boolean mCancelled = false;
+ @Override
+ public void onAnimationStart(RemoteAnimationTarget[] apps,
+ IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
+ }
+
+ @Override
+ public void onAnimationCancelled() {
+ mCancelled = true;
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return null;
+ }
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
index 623559e..70d9b5f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
@@ -30,6 +30,7 @@
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.server.wm.WindowTestUtils.TestAppWindowToken;
@@ -65,6 +66,7 @@
}
@Test
+ @FlakyTest(bugId = 131005232)
public void clipAfterAnim_boundsLayerIsCreated() {
mToken.mNeedsAnimationBoundsLayer = true;
@@ -86,6 +88,7 @@
}
@Test
+ @FlakyTest(bugId = 131005232)
public void clipAfterAnim_boundsLayerIsDestroyed() {
mToken.mNeedsAnimationBoundsLayer = true;
mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
@@ -116,6 +119,7 @@
}
@Test
+ @FlakyTest(bugId = 131005232)
public void clipNoneAnim_boundsLayerIsNotCreated() {
mToken.mNeedsAnimationBoundsLayer = false;
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 064b553..fe45411 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -150,6 +150,7 @@
}
@Test
+ @FlakyTest(bugId = 131005232)
public void testLandscapeSeascapeRotationByApp() {
// Some plumbing to get the service ready for rotation updates.
mWm.mDisplayReady = true;
@@ -504,14 +505,14 @@
private void assertHasStartingWindow(AppWindowToken atoken) {
assertNotNull(atoken.startingSurface);
- assertNotNull(atoken.startingData);
+ assertNotNull(atoken.mStartingData);
assertNotNull(atoken.startingWindow);
}
private void assertNoStartingWindow(AppWindowToken atoken) {
assertNull(atoken.startingSurface);
assertNull(atoken.startingWindow);
- assertNull(atoken.startingData);
+ assertNull(atoken.mStartingData);
atoken.forAllWindows(windowState -> {
assertFalse(windowState.getBaseType() == TYPE_APPLICATION_STARTING);
}, true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index e60e54c..f49a575 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -19,6 +19,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
import static android.os.Build.VERSION_CODES.P;
import static android.os.Build.VERSION_CODES.Q;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -29,6 +30,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
@@ -380,6 +382,14 @@
assertTrue(window1.isFocused());
assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
+
+ // Make sure top focused display not changed if there is a focused app.
+ window1.mAppToken.hiddenRequested = true;
+ window1.getDisplayContent().setFocusedApp(window1.mAppToken);
+ updateFocusedWindow();
+ assertTrue(!window1.isFocused());
+ assertEquals(window1.getDisplayId(),
+ mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
}
/**
@@ -528,6 +538,43 @@
}
@Test
+ public void testOrientationForAspectRatio() {
+ final DisplayContent dc = createNewDisplay();
+
+ // When display content is created its configuration is not yet initialized, which could
+ // cause unnecessary configuration propagation, so initialize it here.
+ final Configuration config = new Configuration();
+ dc.computeScreenConfiguration(config);
+ dc.onRequestedOverrideConfigurationChanged(config);
+
+ // Create a window that requests a fixed orientation. It will define device orientation
+ // by default.
+ final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
+ "window");
+ window.mHasSurface = true;
+ window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
+
+ // --------------------------------
+ // Test non-close-to-square display
+ // --------------------------------
+ dc.mBaseDisplayWidth = 1000;
+ dc.mBaseDisplayHeight = (int) (dc.mBaseDisplayWidth * dc.mCloseToSquareMaxAspectRatio * 2f);
+ dc.configureDisplayPolicy();
+
+ assertEquals("Screen orientation must be defined by the window by default.",
+ window.mAttrs.screenOrientation, dc.getOrientation());
+
+ // ----------------------------
+ // Test close-to-square display
+ // ----------------------------
+ dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
+ dc.configureDisplayPolicy();
+
+ assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
+ SCREEN_ORIENTATION_USER, dc.getOrientation());
+ }
+
+ @Test
public void testDisableDisplayInfoOverrideFromWindowManager() {
final DisplayContent dc = createNewDisplay();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index e90f094..4a87aa4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -21,6 +21,7 @@
import static android.view.Surface.ROTATION_90;
import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
@@ -32,6 +33,7 @@
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
@@ -160,6 +162,25 @@
}
@Test
+ public void layoutWindowLw_keyguardDialog_hideNav() {
+ synchronized (mWm.mGlobalLock) {
+ mWindow.mAttrs.type = TYPE_KEYGUARD_DIALOG;
+ mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ mWindow.mAttrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* uiMode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null /* attached */, mFrames);
+
+ assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0);
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0);
+ }
+ }
+
+ @Test
public void layoutWindowLw_withDisplayCutout() {
synchronized (mWm.mGlobalLock) {
addDisplayCutout();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 1c10ffb0..49d38c0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -394,19 +393,6 @@
verifyOrientationListenerRegistration(0);
}
- @Test
- public void testNotEnablesSensor_ForceDefaultRotation_Squared() throws Exception {
- mBuilder.build();
- configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false);
-
- when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
- when(mMockDisplayPolicy.isAwake()).thenReturn(true);
- when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
- when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
- mTarget.updateOrientationListener();
- verifyOrientationListenerRegistration(0);
- }
-
private void enableOrientationSensor() {
when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
when(mMockDisplayPolicy.isAwake()).thenReturn(true);
@@ -533,15 +519,6 @@
}
@Test
- public void testReturnsUserRotation_ForceDefaultRotation_Squared() throws Exception {
- mBuilder.build();
- configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false);
-
- assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
- Surface.ROTATION_180));
- }
-
- @Test
public void testReturnsLidOpenRotation_LidOpen() throws Exception {
mBuilder.setLidOpenRotation(Surface.ROTATION_90).build();
configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
@@ -643,14 +620,9 @@
width = 1080;
height = 1920;
break;
- case SCREEN_ORIENTATION_LOCKED:
- // We use locked for squared display.
- width = 1080;
- height = 1080;
- break;
default:
- throw new IllegalArgumentException("displayOrientation needs to be landscape, "
- + "portrait or locked, but we got "
+ throw new IllegalArgumentException("displayOrientation needs to be either landscape"
+ + " or portrait, but we got "
+ ActivityInfo.screenOrientationToString(displayOrientation));
}
@@ -660,10 +632,6 @@
.thenReturn(isCar);
when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
.thenReturn(isTv);
- when(mMockDisplayPolicy.getNonDecorDisplayWidth(anyInt(), anyInt(), anyInt(), anyInt(),
- any())).thenReturn(width);
- when(mMockDisplayPolicy.getNonDecorDisplayHeight(anyInt(), anyInt(), anyInt(), anyInt(),
- any())).thenReturn(height);
final int shortSizeDp = (isCar || isTv) ? 540 : 720;
final int longSizeDp = 960;
@@ -831,9 +799,6 @@
.thenReturn(convertRotationToDegrees(mDeskDockRotation));
when(mMockRes.getInteger(com.android.internal.R.integer.config_undockedHdmiRotation))
.thenReturn(convertRotationToDegrees(mUndockedHdmiRotation));
- when(mMockRes.getFloat(
- com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio))
- .thenReturn(1.33f);
mMockSensorManager = mock(SensorManager.class);
when(mMockContext.getSystemService(Context.SENSOR_SERVICE))
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index 652ea7d..336fa04 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -51,6 +51,7 @@
import androidx.test.filters.SmallTest;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.server.LocalServices;
import com.android.server.policy.WindowManagerPolicy;
import org.junit.After;
@@ -588,6 +589,23 @@
getStoredDisplayAttributeValue("shouldShowIme"));
}
+ @Test
+ public void testShouldShowImeWithinForceDesktopMode() {
+ try {
+ // Presume display enabled force desktop mode from developer options.
+ final DisplayContent dc = createMockSimulatedDisplay();
+ mWm.setForceDesktopModeOnExternalDisplays(true);
+ final WindowManagerInternal wmInternal = LocalServices.getService(
+ WindowManagerInternal.class);
+ // Make sure WindowManagerInter#shouldShowIme as true is due to
+ // mForceDesktopModeOnExternalDisplays as true.
+ assertFalse(mWm.mDisplayWindowSettings.shouldShowImeLocked(dc));
+ assertTrue(wmInternal.shouldShowIme(dc.getDisplayId()));
+ } finally {
+ mWm.setForceDesktopModeOnExternalDisplays(false);
+ }
+ }
+
/**
* Prepares display settings and stores in {@link #mStorage}. Uses provided display identifier
* and stores windowingMode=WINDOWING_MODE_PINNED.
diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
index e24eb75..47c76fc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -407,7 +407,7 @@
mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
- // WHEN calling stopLockTaskMode on the root task
+ // WHEN calling clearLockedTasks on the root task
mLockTaskController.clearLockedTasks("testClearLockedTasks");
// THEN the lock task mode should be inactive
@@ -421,6 +421,80 @@
}
@Test
+ public void testClearLockedTasks_noLockSetting_noPassword_deviceIsUnlocked() throws Exception {
+ // GIVEN There is no setting set for LOCK_TO_APP_EXIT_LOCKED
+ Settings.Secure.clearProviderForTest();
+
+ // AND no password is set
+ when(mLockPatternUtils.getKeyguardStoredPasswordQuality(anyInt()))
+ .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
+
+ // AND there is a task record
+ TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
+ mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
+
+ // WHEN calling clearLockedTasks on the root task
+ mLockTaskController.clearLockedTasks("testClearLockedTasks");
+
+ // THEN the device should not be locked
+ verify(mWindowManager, never()).lockNow(any());
+ }
+
+ @Test
+ public void testClearLockedTasks_noLockSetting_password_deviceIsLocked() throws Exception {
+ // GIVEN There is no setting set for LOCK_TO_APP_EXIT_LOCKED
+ Settings.Secure.clearProviderForTest();
+
+ // AND a password is set
+ when(mLockPatternUtils.isSecure(anyInt()))
+ .thenReturn(true);
+
+ // AND there is a task record
+ TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
+ mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
+
+ // WHEN calling clearLockedTasks on the root task
+ mLockTaskController.clearLockedTasks("testClearLockedTasks");
+
+ // THEN the device should be locked
+ verify(mWindowManager, times(1)).lockNow(any());
+ }
+
+ @Test
+ public void testClearLockedTasks_lockSettingTrue_deviceIsLocked() throws Exception {
+ // GIVEN LOCK_TO_APP_EXIT_LOCKED is set to 1
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, 1, mContext.getUserId());
+
+ // AND there is a task record
+ TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
+ mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
+
+ // WHEN calling clearLockedTasks on the root task
+ mLockTaskController.clearLockedTasks("testClearLockedTasks");
+
+ // THEN the device should be locked
+ verify(mWindowManager, times(1)).lockNow(any());
+ }
+
+ @Test
+ public void testClearLockedTasks_lockSettingFalse_doesNotRequirePassword() throws Exception {
+ // GIVEN LOCK_TO_APP_EXIT_LOCKED is set to 1
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, 0, mContext.getUserId());
+
+ // AND there is a task record
+ TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
+ mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
+
+ // WHEN calling clearLockedTasks on the root task
+ mLockTaskController.clearLockedTasks("testClearLockedTasks");
+
+ // THEN the device should be unlocked
+ verify(mWindowManager, never()).lockNow(any());
+ }
+
+ @Test
public void testUpdateLockTaskPackages() {
String[] whitelist1 = {TEST_PACKAGE_NAME, TEST_PACKAGE_NAME_2};
String[] whitelist2 = {TEST_PACKAGE_NAME};
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 385748c..26cd63c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -37,6 +37,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
@@ -163,7 +164,9 @@
// Assume IRecentsAnimationController#cleanupScreenshot called to finish screenshot
// animation.
+ spyOn(mController.mRecentScreenshotAnimator.mAnimatable);
mController.mRecentScreenshotAnimator.cancelAnimation();
+ verify(mController.mRecentScreenshotAnimator.mAnimatable).onAnimationLeashLost(any());
verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, true, false);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index f615823..8b2912c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -20,6 +20,8 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
@@ -28,17 +30,21 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
import android.platform.test.annotations.Presubmit;
import android.view.IRecentsAnimationRunner;
-import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
+import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
+
import org.junit.Before;
import org.junit.Test;
@@ -50,25 +56,93 @@
@Presubmit
public class RecentsAnimationTest extends ActivityTestsBase {
- private Context mContext = InstrumentationRegistry.getContext();
- private ComponentName mRecentsComponent;
+ private final ComponentName mRecentsComponent =
+ new ComponentName(mContext.getPackageName(), "RecentsActivity");
private RecentsAnimationController mRecentsAnimationController;
@Before
public void setUp() throws Exception {
- mRecentsComponent = new ComponentName(mContext.getPackageName(), "RecentsActivity");
- mService = new TestActivityTaskManagerService(mContext);
mRecentsAnimationController = mock(RecentsAnimationController.class);
doReturn(mRecentsAnimationController).when(
mService.mWindowManager).getRecentsAnimationController();
+ doReturn(true).when(mService.mWindowManager).canStartRecentsAnimation();
final RecentTasks recentTasks = mService.getRecentTasks();
spyOn(recentTasks);
- mRecentsComponent = new ComponentName(mContext.getPackageName(), "RecentsActivity");
doReturn(mRecentsComponent).when(recentTasks).getRecentsComponent();
}
@Test
+ public void testRecentsActivityVisiblility() {
+ ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+ ActivityStack recentsStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_RECENTS, true /* onTop */);
+ ActivityRecord recentActivity = new ActivityBuilder(mService)
+ .setComponent(mRecentsComponent)
+ .setCreateTask(true)
+ .setStack(recentsStack)
+ .build();
+ ActivityRecord topActivity = new ActivityBuilder(mService).setCreateTask(true).build();
+ topActivity.fullscreen = true;
+ topActivity.getActivityStack().moveToFront("testRecentsActivityVisiblility");
+
+ doCallRealMethod().when(mRootActivityContainer).ensureActivitiesVisible(
+ any() /* starting */, anyInt() /* configChanges */,
+ anyBoolean() /* preserveWindows */);
+
+ RecentsAnimationCallbacks recentsAnimation = startRecentsActivity(
+ mRecentsComponent, true /* getRecentsAnimation */);
+ // The launch-behind state should make the recents activity visible.
+ assertTrue(recentActivity.visible);
+
+ // Simulate the animation is cancelled without changing the stack order.
+ recentsAnimation.onAnimationFinished(REORDER_KEEP_IN_PLACE, true /* runSychronously */,
+ false /* sendUserLeaveHint */);
+ // The non-top recents activity should be invisible by the restored launch-behind state.
+ assertFalse(recentActivity.visible);
+ }
+
+ @Test
+ public void testSetLaunchTaskBehindOfTargetActivity() {
+ ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+ display.mDisplayContent.mBoundsAnimationController = mock(BoundsAnimationController.class);
+ ActivityStack homeStack = display.getHomeStack();
+ // Assume the home activity support recents.
+ ActivityRecord targetActivity = homeStack.getTopActivity();
+ // Put another home activity in home stack.
+ ActivityRecord anotherHomeActivity = new ActivityBuilder(mService)
+ .setComponent(new ComponentName(mContext.getPackageName(), "Home2"))
+ .setCreateTask(true)
+ .setStack(homeStack)
+ .build();
+ // Start an activity on top so the recents activity can be started.
+ new ActivityBuilder(mService)
+ .setCreateTask(true)
+ .build()
+ .getActivityStack()
+ .moveToFront("Activity start");
+
+ // Start the recents animation.
+ RecentsAnimationCallbacks recentsAnimation = startRecentsActivity(
+ targetActivity.getTaskRecord().getBaseIntent().getComponent(),
+ true /* getRecentsAnimation */);
+ // Ensure launch-behind is set for being visible.
+ assertTrue(targetActivity.mLaunchTaskBehind);
+
+ anotherHomeActivity.moveFocusableActivityToTop("launchAnotherHome");
+ // The current top activity is not the recents so the animation should be canceled.
+ verify(mService.mWindowManager, times(1)).cancelRecentsAnimationSynchronously(
+ eq(REORDER_KEEP_IN_PLACE), any() /* reason */);
+
+ // The test uses mocked RecentsAnimationController so we have to invoke the callback
+ // manually to simulate the flow.
+ recentsAnimation.onAnimationFinished(REORDER_KEEP_IN_PLACE, true /* runSychronously */,
+ false /* sendUserLeaveHint */);
+ // We should restore the launch-behind of the original target activity.
+ assertFalse(targetActivity.mLaunchTaskBehind);
+ }
+
+ @Test
public void testCancelAnimationOnVisibleStackOrderChange() {
ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
display.mDisplayContent.mBoundsAnimationController = mock(BoundsAnimationController.class);
@@ -93,12 +167,9 @@
.setCreateTask(true)
.setStack(fullscreenStack2)
.build();
- doReturn(true).when(mService.mWindowManager).canStartRecentsAnimation();
// Start the recents animation
- Intent recentsIntent = new Intent();
- recentsIntent.setComponent(mRecentsComponent);
- mService.startRecentsActivity(recentsIntent, null, mock(IRecentsAnimationRunner.class));
+ startRecentsActivity();
fullscreenStack.moveToFront("Activity start");
@@ -140,12 +211,9 @@
.setCreateTask(true)
.setStack(fullscreenStack2)
.build();
- doReturn(true).when(mService.mWindowManager).canStartRecentsAnimation();
// Start the recents animation
- Intent recentsIntent = new Intent();
- recentsIntent.setComponent(mRecentsComponent);
- mService.startRecentsActivity(recentsIntent, null, mock(IRecentsAnimationRunner.class));
+ startRecentsActivity();
fullscreenStack.remove();
@@ -154,4 +222,32 @@
eq(REORDER_KEEP_IN_PLACE), any());
verify(mRecentsAnimationController, times(0)).cancelOnNextTransitionStart();
}
+
+ private void startRecentsActivity() {
+ startRecentsActivity(mRecentsComponent, false /* getRecentsAnimation */);
+ }
+
+ /**
+ * @return non-null {@link RecentsAnimationCallbacks} if the given {@code getRecentsAnimation}
+ * is {@code true}.
+ */
+ private RecentsAnimationCallbacks startRecentsActivity(ComponentName recentsComponent,
+ boolean getRecentsAnimation) {
+ RecentsAnimationCallbacks[] recentsAnimation = { null };
+ if (getRecentsAnimation) {
+ doAnswer(invocation -> {
+ // The callback is actually RecentsAnimation.
+ recentsAnimation[0] = invocation.getArgument(2);
+ return null;
+ }).when(mService.mWindowManager).initializeRecentsAnimation(
+ anyInt() /* targetActivityType */, any() /* recentsAnimationRunner */,
+ any() /* callbacks */, anyInt() /* displayId */, any() /* recentTaskIds */);
+ }
+
+ Intent recentsIntent = new Intent();
+ recentsIntent.setComponent(recentsComponent);
+ mService.startRecentsActivity(recentsIntent, null /* assistDataReceiver */,
+ mock(IRecentsAnimationRunner.class));
+ return recentsAnimation[0];
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index b2084f8..0f7b35c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -61,6 +61,7 @@
import androidx.test.filters.MediumTest;
import com.android.internal.app.ResolverActivity;
+import com.android.server.wm.ActivityStack.ActivityState;
import org.junit.Before;
import org.junit.Test;
@@ -394,6 +395,52 @@
}
/**
+ * Verify that a lingering transition is being executed in case the activity to be resumed is
+ * already resumed
+ */
+ @Test
+ public void testResumeActivityLingeringTransition() {
+ // Create a stack at top.
+ final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+ final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_STANDARD, false /* onTop */));
+ final TaskRecord task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
+ final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build();
+ activity.setState(ActivityState.RESUMED, "test");
+
+ // Assume the stack is at the topmost position
+ assertTrue(targetStack.isTopStackOnDisplay());
+
+ // Use the stack as target to resume.
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
+
+ // Verify the lingering app transition is being executed because it's already resumed
+ verify(targetStack, times(1)).executeAppTransition(any());
+ }
+
+ @Test
+ public void testResumeActivityLingeringTransition_notExecuted() {
+ // Create a stack at bottom.
+ final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+ final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_STANDARD, false /* onTop */));
+ final TaskRecord task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
+ final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build();
+ activity.setState(ActivityState.RESUMED, "test");
+ display.positionChildAtBottom(targetStack);
+
+ // Assume the stack is at the topmost position
+ assertFalse(targetStack.isTopStackOnDisplay());
+ doReturn(targetStack).when(mRootActivityContainer).getTopDisplayFocusedStack();
+
+ // Use the stack as target to resume.
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
+
+ // Verify the lingering app transition is being executed because it's already resumed
+ verify(targetStack, never()).executeAppTransition(any());
+ }
+
+ /**
* Tests that home activities can be started on the displays that supports system decorations.
*/
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 4f03726..340e741 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -17,7 +17,9 @@
package com.android.server.wm;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions;
@@ -178,6 +180,20 @@
}
@Test
+ public void testOnAnimationLeashLostWhenAnimatableParentSurfaceControlNull() {
+ mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+ spyOn(mAnimatable);
+
+ // Verify onAnimationLeashLost will be called even animatable's parent surface control lost.
+ doReturn(null).when(mAnimatable).getParentSurfaceControl();
+ mAnimatable.mSurfaceAnimator.cancelAnimation();
+
+ final SurfaceControl leash = mAnimatable.mLeash;
+ verify(mTransaction).remove(eq(leash));
+ verify(mAnimatable).onAnimationLeashLost(mTransaction);
+ }
+
+ @Test
public void testDeferFinish() {
// Start animation
@@ -272,7 +288,7 @@
}
@Override
- public void onAnimationLeashDestroyed(Transaction t) {
+ public void onAnimationLeashLost(Transaction t) {
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 98d055c..3a8d3b7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -493,4 +493,30 @@
assertTrue(window.isVisible());
assertTrue(window.isVisibleByPolicy());
}
+
+ @Test
+ public void testGetTransformationMatrix() {
+ synchronized (mWm.mGlobalLock) {
+ final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
+ win0.getFrameLw().offsetTo(1, 0);
+
+ final DisplayContent dc = createNewDisplay();
+ dc.reparentDisplayContent(win0, win0.getSurfaceControl());
+ dc.updateLocation(win0, 2, 0);
+
+ final float[] values = new float[9];
+ final Matrix matrix = new Matrix();
+ final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+ final WindowState win1 = createWindow(null, TYPE_APPLICATION, dc, "win1");
+ win1.mHasSurface = true;
+ win1.mSurfaceControl = mock(SurfaceControl.class);
+ win1.getFrameLw().offsetTo(3, 0);
+ win1.updateSurfacePosition(t);
+ win1.getTransformationMatrix(values, matrix);
+
+ matrix.getValues(values);
+ assertEquals(6f, values[Matrix.MTRANS_X], 0f);
+ assertEquals(0f, values[Matrix.MTRANS_Y], 0f);
+ }
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 8c37ca5e..3a702cb9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -19,6 +19,7 @@
import static android.app.AppOpsManager.OP_NONE;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.os.Process.SYSTEM_UID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.View.VISIBLE;
@@ -445,4 +446,13 @@
return new WindowTestUtils.TestWindowState(mWm, mMockSession, mIWindow, attrs, token);
}
}
+
+ /** Creates a {@link DisplayContent} as parts of simulate display info for test. */
+ DisplayContent createMockSimulatedDisplay() {
+ DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.copyFrom(mDisplayInfo);
+ displayInfo.type = Display.TYPE_VIRTUAL;
+ displayInfo.ownerUid = SYSTEM_UID;
+ return createNewDisplay(displayInfo);
+ }
}
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 7786627..75e8fb5 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -1356,7 +1356,7 @@
private void fetchCarrierPrivilegedAppsLocked() {
TelephonyManager telephonyManager =
mContext.getSystemService(TelephonyManager.class);
- mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivileges();
+ mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivilegesForAllPhones();
mHaveCarrierPrivilegedApps = true;
if (DEBUG) {
Slog.d(TAG, "apps with carrier privilege " + mCarrierPrivilegedApps);
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index faf6ee2..0f3050f 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -120,6 +120,7 @@
@Override
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
switch (vol.type) {
+ case VolumeInfo.TYPE_PUBLIC:
case VolumeInfo.TYPE_PRIVATE:
case VolumeInfo.TYPE_EMULATED:
if (newState == VolumeInfo.STATE_MOUNTED) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index c55bb3c..5197b3b 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -17,7 +17,6 @@
package com.android.server.usage;
import android.app.usage.TimeSparseArray;
-import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.os.Build;
@@ -94,12 +93,10 @@
// Persist versioned backup files.
// Should be false, except when testing new versions
- // STOPSHIP: b/111422946 this should be false on launch
- static final boolean KEEP_BACKUP_DIR = true;
+ static final boolean KEEP_BACKUP_DIR = false;
private static final String TAG = "UsageStatsDatabase";
- // STOPSHIP: b/111422946 this should be boolean DEBUG = UsageStatsService.DEBUG; on launch
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = UsageStatsService.DEBUG;
private static final String BAK_SUFFIX = ".bak";
private static final String CHECKED_IN_SUFFIX = UsageStatsXml.CHECKED_IN_SUFFIX;
private static final String RETENTION_LEN_KEY = "ro.usagestats.chooser.retention";
@@ -872,111 +869,6 @@
Slog.e(TAG, "UsageStatsDatabase", e);
throw e;
}
- // If old version, don't bother sanity checking
- if (version < 4) return;
-
- // STOPSHIP: b/111422946, b/115429334
- // Everything below this comment is sanity check against the new database version.
- // After the new version has soaked for some time the following should removed.
- // The goal of this check is to make sure the the ProtoInputStream is properly reading from
- // the UsageStats files.
- final StringBuilder sb = new StringBuilder();
- final int failureLogLimit = 10;
- int failures = 0;
-
- final int packagesSize = statsOut.packageStats.size();
- for (int i = 0; i < packagesSize; i++) {
- final UsageStats stat = statsOut.packageStats.valueAt(i);
- if (stat == null) {
- // ArrayMap may contain null values, skip them
- continue;
- }
- if (stat.mPackageName.isEmpty()) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnexpected empty usage stats package name loaded");
- }
- }
- if (stat.mBeginTimeStamp > statsOut.endTime) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnreasonable usage stats stat begin timestamp ");
- sb.append(stat.mBeginTimeStamp);
- sb.append(" loaded (beginTime : ");
- sb.append(statsOut.beginTime);
- sb.append(", endTime : ");
- sb.append(statsOut.endTime);
- sb.append(")");
- }
- }
- if (stat.mEndTimeStamp > statsOut.endTime) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnreasonable usage stats stat end timestamp ");
- sb.append(stat.mEndTimeStamp);
- sb.append(" loaded (beginTime : ");
- sb.append(statsOut.beginTime);
- sb.append(", endTime : ");
- sb.append(statsOut.endTime);
- sb.append(")");
- }
- }
- if (stat.mLastTimeUsed > statsOut.endTime) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnreasonable usage stats stat last used timestamp ");
- sb.append(stat.mLastTimeUsed);
- sb.append(" loaded (beginTime : ");
- sb.append(statsOut.beginTime);
- sb.append(", endTime : ");
- sb.append(statsOut.endTime);
- sb.append(")");
- }
- }
- }
-
- final int eventSize = statsOut.events.size();
- for (int i = 0; i < eventSize; i++) {
- final UsageEvents.Event event = statsOut.events.get(i);
- if (event.mPackage.isEmpty()) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnexpected empty empty package name loaded");
- }
- }
- if (event.mTimeStamp < statsOut.beginTime || event.mTimeStamp > statsOut.endTime) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnexpected event timestamp ");
- sb.append(event.mTimeStamp);
- sb.append(" loaded (beginTime : ");
- sb.append(statsOut.beginTime);
- sb.append(", endTime : ");
- sb.append(statsOut.endTime);
- sb.append(")");
- }
- }
- if (event.mEventType < 0 || event.mEventType > UsageEvents.Event.MAX_EVENT_TYPE) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnexpected event type ");
- sb.append(event.mEventType);
- sb.append(" loaded");
- }
- }
- if ((event.mFlags & ~UsageEvents.Event.VALID_FLAG_BITS) != 0) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnexpected event flag bit 0b");
- sb.append(Integer.toBinaryString(event.mFlags));
- sb.append(" loaded");
- }
- }
- }
-
- if (failures != 0) {
- if (failures > failureLogLimit) {
- sb.append("\nFailure log limited (");
- sb.append(failures);
- sb.append(" total failures found!)");
- }
- sb.append("\nError found in:\n");
- sb.append(file.getBaseFile().getAbsolutePath());
- sb.append("\nPlease go to b/115429334 to help root cause this issue");
- Slog.wtf(TAG, sb.toString());
- }
}
private void readLocked(InputStream in, IntervalStats statsOut) throws IOException {
@@ -1280,4 +1172,16 @@
pw.decreaseIndent();
}
}
+
+ IntervalStats readIntervalStatsForFile(int interval, long fileName) {
+ synchronized (mLock) {
+ final IntervalStats stats = new IntervalStats();
+ try {
+ readLocked(mSortedStatFiles[interval].get(fileName, null), stats);
+ return stats;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ }
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 1ec680f..2298aa1 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -774,6 +774,62 @@
mAppTimeLimit.dump(remainingArgs, pw);
}
return;
+ } else if ("file".equals(arg)) {
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ if (i + 1 >= args.length) {
+ // dump everything for all users
+ final int numUsers = mUserState.size();
+ for (int user = 0; user < numUsers; user++) {
+ ipw.println("user=" + mUserState.keyAt(user));
+ ipw.increaseIndent();
+ mUserState.valueAt(user).dumpFile(ipw, null);
+ ipw.decreaseIndent();
+ }
+ } else {
+ final int user;
+ try {
+ user = Integer.valueOf(args[i + 1]);
+ } catch (NumberFormatException nfe) {
+ ipw.println("invalid user specified.");
+ return;
+ }
+ if (mUserState.indexOfKey(user) < 0) {
+ ipw.println("the specified user does not exist.");
+ return;
+ }
+ final String[] remainingArgs = Arrays.copyOfRange(
+ args, i + 2, args.length);
+ // dump everything for the specified user
+ mUserState.get(user).dumpFile(ipw, remainingArgs);
+ }
+ return;
+ } else if ("database-info".equals(arg)) {
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ if (i + 1 >= args.length) {
+ // dump info for all users
+ final int numUsers = mUserState.size();
+ for (int user = 0; user < numUsers; user++) {
+ ipw.println("user=" + mUserState.keyAt(user));
+ ipw.increaseIndent();
+ mUserState.valueAt(user).dumpDatabaseInfo(ipw);
+ ipw.decreaseIndent();
+ }
+ } else {
+ final int user;
+ try {
+ user = Integer.valueOf(args[i + 1]);
+ } catch (NumberFormatException nfe) {
+ ipw.println("invalid user specified.");
+ return;
+ }
+ if (mUserState.indexOfKey(user) < 0) {
+ ipw.println("the specified user does not exist.");
+ return;
+ }
+ // dump info only for the specified user
+ mUserState.get(user).dumpDatabaseInfo(ipw);
+ }
+ return;
} else if (arg != null && !arg.startsWith("-")) {
// Anything else that doesn't start with '-' is a pkg to filter
pkg = arg;
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 26bfcc9..11c0e4a 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -28,6 +28,7 @@
import android.app.usage.ConfigurationStats;
import android.app.usage.EventList;
import android.app.usage.EventStats;
+import android.app.usage.TimeSparseArray;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStats;
@@ -38,6 +39,7 @@
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.AtomicFile;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -75,9 +77,6 @@
private String mLastBackgroundedPackage;
private final int mUserId;
- // STOPSHIP: Temporary member variable for debugging b/110930764.
- private Event mLastEvent;
-
private static final long[] INTERVAL_LENGTH = new long[] {
UnixCalendar.DAY_IN_MILLIS, UnixCalendar.WEEK_IN_MILLIS,
UnixCalendar.MONTH_IN_MILLIS, UnixCalendar.YEAR_IN_MILLIS
@@ -170,8 +169,6 @@
+ eventToString(event.mEventType));
}
- mLastEvent = new Event(event);
-
if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
// Need to rollover
rolloverStats(event.mTimeStamp);
@@ -327,36 +324,6 @@
Slog.d(TAG, mLogPrefix + "Requesting stats after " + beginTime + " but latest is "
+ currentStats.endTime);
}
-
- // STOPSHIP: Temporary logging for b/110930764.
- if (intervalType == INTERVAL_DAILY
- && mLastEvent != null && mLastEvent.mTimeStamp >= beginTime) {
- final IntervalStats diskStats = mDatabase.getLatestUsageStats(
- INTERVAL_DAILY);
- StringBuilder sb = new StringBuilder(256);
- sb.append("Recent UsageStats missing! timeRange : ");
- sb.append(beginTime);
- sb.append(", ");
- sb.append(endTime);
- sb.append("\nLast reported Usage Event time : ");
- sb.append(mLastEvent.mTimeStamp);
- if (currentStats == null) {
- sb.append("\nNo in memory event stats available.");
- } else {
- sb.append("\nLast in memory event time : ");
- sb.append(currentStats.endTime);
- sb.append("\nLast save time: ");
- sb.append(currentStats.lastTimeSaved);
- }
- if (diskStats == null) {
- sb.append("\nNo on disk event stats available.");
- } else {
- sb.append("\nLast on disk event time : ");
- sb.append(diskStats.endTime);
- }
- Slog.wtf(TAG, sb.toString());
- }
-
// Nothing newer available.
return null;
}
@@ -665,6 +632,77 @@
mDatabase.dump(pw, compact);
}
+ void dumpDatabaseInfo(IndentingPrintWriter ipw) {
+ mDatabase.dump(ipw, false);
+ }
+
+ void dumpFile(IndentingPrintWriter ipw, String[] args) {
+ if (args == null || args.length == 0) {
+ // dump all files for every interval for specified user
+ final int numIntervals = mDatabase.mSortedStatFiles.length;
+ for (int interval = 0; interval < numIntervals; interval++) {
+ ipw.println("interval=" + intervalToString(interval));
+ ipw.increaseIndent();
+ dumpFileDetailsForInterval(ipw, interval);
+ ipw.decreaseIndent();
+ }
+ } else {
+ final int interval;
+ try {
+ final int intervalValue = stringToInterval(args[0]);
+ if (intervalValue == -1) {
+ interval = Integer.valueOf(args[0]);
+ } else {
+ interval = intervalValue;
+ }
+ } catch (NumberFormatException nfe) {
+ ipw.println("invalid interval specified.");
+ return;
+ }
+ if (interval < 0 || interval >= mDatabase.mSortedStatFiles.length) {
+ ipw.println("the specified interval does not exist.");
+ return;
+ }
+ if (args.length == 1) {
+ // dump all files in the specified interval
+ dumpFileDetailsForInterval(ipw, interval);
+ } else {
+ // dump details only for the specified filename
+ final long filename;
+ try {
+ filename = Long.valueOf(args[1]);
+ } catch (NumberFormatException nfe) {
+ ipw.println("invalid filename specified.");
+ return;
+ }
+ final IntervalStats stats = mDatabase.readIntervalStatsForFile(interval, filename);
+ if (stats == null) {
+ ipw.println("the specified filename does not exist.");
+ return;
+ }
+ dumpFileDetails(ipw, stats, Long.valueOf(args[1]));
+ }
+ }
+ }
+
+ private void dumpFileDetailsForInterval(IndentingPrintWriter ipw, int interval) {
+ final TimeSparseArray<AtomicFile> files = mDatabase.mSortedStatFiles[interval];
+ final int numFiles = files.size();
+ for (int i = 0; i < numFiles; i++) {
+ final long filename = files.keyAt(i);
+ final IntervalStats stats = mDatabase.readIntervalStatsForFile(interval, filename);
+ dumpFileDetails(ipw, stats, filename);
+ ipw.println();
+ }
+ }
+
+ private void dumpFileDetails(IndentingPrintWriter ipw, IntervalStats stats, long filename) {
+ ipw.println("file=" + filename);
+ ipw.increaseIndent();
+ printIntervalStats(ipw, stats, false, false, null);
+ ipw.decreaseIndent();
+ }
+
static String formatDateTime(long dateTime, boolean pretty) {
if (pretty) {
return "\"" + sDateFormat.format(dateTime)+ "\"";
@@ -908,6 +946,21 @@
}
}
+ private static int stringToInterval(String interval) {
+ switch (interval.toLowerCase()) {
+ case "daily":
+ return INTERVAL_DAILY;
+ case "weekly":
+ return INTERVAL_WEEKLY;
+ case "monthly":
+ return INTERVAL_MONTHLY;
+ case "yearly":
+ return INTERVAL_YEARLY;
+ default:
+ return -1;
+ }
+ }
+
private static String eventToString(int eventType) {
switch (eventType) {
case Event.NONE:
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 4874bce..5239d97 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -35,7 +35,9 @@
import libcore.io.IoUtils;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
/**
* UsbAlsaManager manages USB audio and MIDI devices.
@@ -61,6 +63,50 @@
private final ArrayList<UsbAlsaDevice> mAlsaDevices = new ArrayList<UsbAlsaDevice>();
private UsbAlsaDevice mSelectedDevice;
+ //
+ // Device Blacklist
+ //
+ // This exists due to problems with Sony game controllers which present as an audio device
+ // even if no headset is connected and have no way to set the volume on the unit.
+ // Handle this by simply declining to use them as an audio device.
+ private static final int USB_VENDORID_SONY = 0x054C;
+ private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT1 = 0x05C4;
+ private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT2 = 0x09CC;
+
+ private static final int USB_BLACKLIST_OUTPUT = 0x0001;
+ private static final int USB_BLACKLIST_INPUT = 0x0002;
+
+ private static class BlackListEntry {
+ final int mVendorId;
+ final int mProductId;
+ final int mFlags;
+
+ BlackListEntry(int vendorId, int productId, int flags) {
+ mVendorId = vendorId;
+ mProductId = productId;
+ mFlags = flags;
+ }
+ }
+
+ static final List<BlackListEntry> sDeviceBlacklist = Arrays.asList(
+ new BlackListEntry(USB_VENDORID_SONY,
+ USB_PRODUCTID_PS4CONTROLLER_ZCT1,
+ USB_BLACKLIST_OUTPUT),
+ new BlackListEntry(USB_VENDORID_SONY,
+ USB_PRODUCTID_PS4CONTROLLER_ZCT2,
+ USB_BLACKLIST_OUTPUT));
+
+ private static boolean isDeviceBlacklisted(int vendorId, int productId, int flags) {
+ for (BlackListEntry entry : sDeviceBlacklist) {
+ if (entry.mVendorId == vendorId && entry.mProductId == productId) {
+ // see if the type flag is set
+ return (entry.mFlags & flags) != 0;
+ }
+ }
+
+ return false;
+ }
+
/**
* List of connected MIDI devices
*/
@@ -179,8 +225,12 @@
}
// Add it to the devices list
- boolean hasInput = parser.hasInput();
- boolean hasOutput = parser.hasOutput();
+ boolean hasInput = parser.hasInput()
+ && !isDeviceBlacklisted(usbDevice.getVendorId(), usbDevice.getProductId(),
+ USB_BLACKLIST_INPUT);
+ boolean hasOutput = parser.hasOutput()
+ && !isDeviceBlacklisted(usbDevice.getVendorId(), usbDevice.getProductId(),
+ USB_BLACKLIST_OUTPUT);
if (DEBUG) {
Slog.d(TAG, "hasInput: " + hasInput + " hasOutput:" + hasOutput);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index e1ffb0f..d77ea6e 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -77,6 +77,7 @@
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.LocalServices;
+import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemService;
import com.android.server.UiThread;
import com.android.server.soundtrigger.SoundTriggerInternal;
@@ -1283,7 +1284,9 @@
mRm.addOnRoleHoldersChangedListenerAsUser(executor, this, UserHandle.ALL);
UserHandle currentUser = UserHandle.of(LocalServices.getService(
ActivityManagerInternal.class).getCurrentUserId());
- onRoleHoldersChanged(RoleManager.ROLE_ASSISTANT, currentUser);
+ SystemServerInitThreadPool.get().submit(() -> onRoleHoldersChanged(
+ RoleManager.ROLE_ASSISTANT, currentUser),
+ "VoiceInteractionManagerService RoleObserver initialization");
}
private @NonNull String getDefaultRecognizer(@NonNull UserHandle user) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 000a347..f16dec6 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -253,7 +253,7 @@
if (data == null) {
try {
- mSession.handleAssist(-1, null, null, null, null, -1, 0);
+ mSession.handleAssist(-1, null, null, null, null, 0, 0);
} catch (RemoteException e) {
// Ignore
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index db63198..eefaf47 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -33,6 +33,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -161,6 +162,10 @@
* getActivity().getPackageName());
* startActivity(intent);
* </pre>
+ * <p>
+ * This is no longer supported since Q, please use
+ * {@link android.app.role.RoleManager#createRequestRoleIntent(String)} with
+ * {@link android.app.role.RoleManager#ROLE_DIALER} instead.
*/
public static final String ACTION_CHANGE_DEFAULT_DIALER =
"android.telecom.action.CHANGE_DEFAULT_DIALER";
@@ -849,15 +854,18 @@
/**
* Returns the current SIM call manager. Apps must be prepared for this method to return
- * {@code null}, indicating that there currently exists no user-chosen default
- * {@code PhoneAccount}.
+ * {@code null}, indicating that there currently exists no SIM call manager {@link PhoneAccount}
+ * for the default voice subscription.
*
- * @return The phone account handle of the current sim call manager.
+ * @return The phone account handle of the current sim call manager for the default voice
+ * subscription.
+ * @see SubscriptionManager#getDefaultVoiceSubscriptionId()
*/
public PhoneAccountHandle getSimCallManager() {
try {
if (isServiceConnected()) {
- return getTelecomService().getSimCallManager();
+ return getTelecomService().getSimCallManager(
+ SubscriptionManager.getDefaultSubscriptionId());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getSimCallManager");
@@ -866,9 +874,32 @@
}
/**
- * Returns the current SIM call manager for the specified user. Apps must be prepared for this
- * method to return {@code null}, indicating that there currently exists no user-chosen default
- * {@code PhoneAccount}.
+ * Returns current SIM call manager for the Telephony Subscription ID specified. Apps must be
+ * prepared for this method to return {@code null}, indicating that there currently exists no
+ * SIM call manager {@link PhoneAccount} for the subscription specified.
+ *
+ * @param subscriptionId The Telephony Subscription ID that the SIM call manager should be
+ * queried for.
+ * @return The phone account handle of the current sim call manager.
+ * @see SubscriptionManager#getActiveSubscriptionInfoList()
+ * @hide
+ */
+ public PhoneAccountHandle getSimCallManagerForSubscription(int subscriptionId) {
+ try {
+ if (isServiceConnected()) {
+ return getTelecomService().getSimCallManager(subscriptionId);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecomService#getSimCallManager");
+ }
+ return null;
+ }
+
+ /**
+ * Returns the current SIM call manager for the user-chosen default Telephony Subscription ID
+ * (see {@link SubscriptionManager#getDefaultSubscriptionId()}) and the specified user. Apps
+ * must be prepared for this method to return {@code null}, indicating that there currently
+ * exists no SIM call manager {@link PhoneAccount} for the default voice subscription.
*
* @return The phone account handle of the current sim call manager.
*
@@ -889,8 +920,8 @@
/**
* Returns the current connection manager. Apps must be prepared for this method to return
- * {@code null}, indicating that there currently exists no user-chosen default
- * {@code PhoneAccount}.
+ * {@code null}, indicating that there currently exists no Connection Manager
+ * {@link PhoneAccount} for the default voice subscription.
*
* @return The phone account handle of the current connection manager.
* @hide
@@ -1420,6 +1451,9 @@
* foreground call is ended.
* <p>
* Requires permission {@link android.Manifest.permission#ANSWER_PHONE_CALLS}.
+ * <p>
+ * Note: this method CANNOT be used to end ongoing emergency calls and will return {@code false}
+ * if an attempt is made to end an emergency call.
*
* @return {@code true} if there is a call which will be rejected or terminated, {@code false}
* otherwise.
@@ -1427,8 +1461,6 @@
* instead. Apps performing call screening should use the {@link CallScreeningService} API
* instead.
*/
-
-
@RequiresPermission(Manifest.permission.ANSWER_PHONE_CALLS)
@Deprecated
public boolean endCall() {
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 5cd46ca..4fcda4d 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -97,7 +97,7 @@
/**
* @see TelecomServiceImpl#getSimCallManager
*/
- PhoneAccountHandle getSimCallManager();
+ PhoneAccountHandle getSimCallManager(int subId);
/**
* @see TelecomServiceImpl#getSimCallManagerForUser
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 9bba2e8..8e56fe7 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -892,6 +892,10 @@
* user whether they want to replace the current default
* SMS application with the one specified in
* {@link #EXTRA_PACKAGE_NAME}.
+ * <p>
+ * This is no longer supported since Q, please use
+ * {@link android.app.role.RoleManager#createRequestRoleIntent(String)} with
+ * {@link android.app.role.RoleManager#ROLE_SMS} instead.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_CHANGE_DEFAULT =
@@ -902,6 +906,10 @@
* extra for {@link #ACTION_CHANGE_DEFAULT}
*
* @see #ACTION_CHANGE_DEFAULT
+ * <p>
+ * This is no longer supported since Q, please use
+ * {@link android.app.role.RoleManager#createRequestRoleIntent(String)} with
+ * {@link android.app.role.RoleManager#ROLE_SMS} instead.
*/
public static final String EXTRA_PACKAGE_NAME = "package";
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 69500d7..6ba359b 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -836,13 +836,6 @@
"carrier_metered_roaming_apn_types_strings";
/**
- * Default APN types that are metered on IWLAN by the carrier
- * @hide
- */
- public static final String KEY_CARRIER_METERED_IWLAN_APN_TYPES_STRINGS =
- "carrier_metered_iwlan_apn_types_strings";
-
- /**
* CDMA carrier ERI (Enhanced Roaming Indicator) file name
* @hide
*/
@@ -2791,7 +2784,7 @@
/**
* Control Plane / SUPL NI emergency extension time in seconds. Default to "0".
*/
- public static final String KEY_ES_EXTENSION_SEC = KEY_PREFIX + "es_extension_sec";
+ public static final String KEY_ES_EXTENSION_SEC_STRING = KEY_PREFIX + "es_extension_sec";
/**
* Space separated list of Android package names of proxy applications representing
@@ -2799,7 +2792,15 @@
* the framework, as managed by IGnssVisibilityControl.hal. For example,
* "com.example.mdt com.example.ims".
*/
- public static final String KEY_NFW_PROXY_APPS = KEY_PREFIX + "nfw_proxy_apps";
+ public static final String KEY_NFW_PROXY_APPS_STRING = KEY_PREFIX + "nfw_proxy_apps";
+
+ /**
+ * Specify whether to post a notification on the status bar whenever device location is
+ * provided for non-framework location requests in user-initiated emergency use cases.
+ * 0 - Do not post notification. This is default.
+ * 1 - Post notification for all request types.
+ */
+ public static final String KEY_ES_NOTIFY_INT = KEY_PREFIX + "es_notify_int";
private static PersistableBundle getDefaults() {
PersistableBundle defaults = new PersistableBundle();
@@ -2813,12 +2814,66 @@
defaults.putString(KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING, "1");
defaults.putString(KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, "0");
defaults.putString(KEY_GPS_LOCK_STRING, "3");
- defaults.putString(KEY_ES_EXTENSION_SEC, "0");
- defaults.putString(KEY_NFW_PROXY_APPS, "");
+ defaults.putString(KEY_ES_EXTENSION_SEC_STRING, "0");
+ defaults.putString(KEY_NFW_PROXY_APPS_STRING, "");
+ defaults.putInt(KEY_ES_NOTIFY_INT, 0);
return defaults;
}
}
+ /**
+ * Wi-Fi configs used in Carrier Wi-Fi application.
+ * TODO(b/132059890): Expose it in a future release as systemapi.
+ *
+ * @hide
+ */
+ public static final class Wifi {
+ /** Prefix of all Wifi.KEY_* constants. */
+ public static final String KEY_PREFIX = "wifi.";
+
+ /**
+ * Whenever any information under wifi namespace is changed, the version should be
+ * incremented by 1 so that the device is able to figure out the latest profiles based on
+ * the version.
+ */
+ public static final String KEY_CARRIER_PROFILES_VERSION_INT =
+ KEY_PREFIX + "carrier_profiles_version_int";
+
+ /**
+ * It contains the package name of connection manager that the carrier owns.
+ *
+ * <P>Once it is installed, the profiles installed by Carrier Wi-Fi Application
+ * will be deleted.
+ * Once it is uninstalled, Carrier Wi-Fi Application will re-install the latest profiles.
+ */
+ public static final String KEY_CARRIER_CONNECTION_MANAGER_PACKAGE_STRING =
+ KEY_PREFIX + "carrier_connection_manager_package_string";
+ /**
+ * It is to have the list of wifi networks profiles which contain the information about
+ * the wifi-networks to which carrier wants the device to connect.
+ */
+ public static final String KEY_NETWORK_PROFILES_STRING_ARRAY =
+ KEY_PREFIX + "network_profiles_string_array";
+
+ /**
+ * It is to have the list of Passpoint profiles which contain the information about
+ * the Passpoint networks to which carrier wants the device to connect.
+ */
+ public static final String KEY_PASSPOINT_PROFILES_STRING_ARRAY =
+ KEY_PREFIX + "passpoint_profiles_string_array";
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ defaults.putInt(KEY_CARRIER_PROFILES_VERSION_INT, -1);
+ defaults.putString(KEY_CARRIER_CONNECTION_MANAGER_PACKAGE_STRING, null);
+ defaults.putStringArray(KEY_NETWORK_PROFILES_STRING_ARRAY, null);
+ defaults.putStringArray(KEY_PASSPOINT_PROFILES_STRING_ARRAY, null);
+ return defaults;
+ }
+
+ private Wifi() {}
+ }
+
/**
* An int array containing CDMA enhanced roaming indicator values for Home (non-roaming) network.
* The default values come from 3GPP2 C.R1001 table 8.1-1.
@@ -2911,6 +2966,15 @@
public static final String KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY =
"gsm_rssi_thresholds_int_array";
+ /**
+ * Determines whether Wireless Priority Service call is supported over IMS.
+ *
+ * See Wireless Priority Service from https://www.fcc.gov/general/wireless-priority-service-wps
+ * @hide
+ */
+ public static final String KEY_SUPPORT_WPS_OVER_IMS_BOOL =
+ "support_wps_over_ims_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -3045,15 +3109,6 @@
new String[]{"default", "mms", "dun", "supl"});
sDefaults.putStringArray(KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
new String[]{"default", "mms", "dun", "supl"});
- // By default all APNs should be unmetered if the device is on IWLAN. However, we add
- // default APN as metered here as a workaround for P because in some cases, a data
- // connection was brought up on cellular, but later on the device camped on IWLAN. That
- // data connection was incorrectly treated as unmetered due to the current RAT IWLAN.
- // Marking it as metered for now can workaround the issue.
- // Todo: This will be fixed in Q when IWLAN full refactoring is completed.
- sDefaults.putStringArray(KEY_CARRIER_METERED_IWLAN_APN_TYPES_STRINGS,
- new String[]{"default"});
-
sDefaults.putIntArray(KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY,
new int[]{
4, /* IS95A */
@@ -3307,6 +3362,7 @@
/* Default value is 10 seconds. */
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG, 10000);
sDefaults.putAll(Gps.getDefaults());
+ sDefaults.putAll(Wifi.getDefaults());
sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
new int[] {
1 /* Roaming Indicator Off */
@@ -3327,6 +3383,7 @@
-97, /* SIGNAL_STRENGTH_GOOD */
-89, /* SIGNAL_STRENGTH_GREAT */
});
+ sDefaults.putBoolean(KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);
}
/**
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 3ce28a4..271195b 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -62,6 +62,8 @@
/**
* Stop listening for updates.
+ *
+ * The PhoneStateListener is not tied to any subscription and unregistered for any update.
*/
public static final int LISTEN_NONE = 0;
@@ -444,7 +446,13 @@
}
/**
- * Callback invoked when device service state changes.
+ * Callback invoked when device service state changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
* @see ServiceState#STATE_EMERGENCY_ONLY
* @see ServiceState#STATE_IN_SERVICE
@@ -456,7 +464,13 @@
}
/**
- * Callback invoked when network signal strength changes.
+ * Callback invoked when network signal strength changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
* @see ServiceState#STATE_EMERGENCY_ONLY
* @see ServiceState#STATE_IN_SERVICE
@@ -470,21 +484,39 @@
}
/**
- * Callback invoked when the message-waiting indicator changes.
+ * Callback invoked when the message-waiting indicator changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
*/
public void onMessageWaitingIndicatorChanged(boolean mwi) {
// default implementation empty
}
/**
- * Callback invoked when the call-forwarding indicator changes.
+ * Callback invoked when the call-forwarding indicator changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
*/
public void onCallForwardingIndicatorChanged(boolean cfi) {
// default implementation empty
}
/**
- * Callback invoked when device cell location changes.
+ * Callback invoked when device cell location changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
*/
public void onCellLocationChanged(CellLocation location) {
// default implementation empty
@@ -493,7 +525,14 @@
/**
* Callback invoked when device call state changes.
* <p>
- * Reports the state of Telephony (mobile) calls on the device.
+ * Reports the state of Telephony (mobile) calls on the device for the registered subscription.
+ * <p>
+ * Note: the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
* <p>
* Note: The state returned here may differ from that returned by
* {@link TelephonyManager#getCallState()}. Receivers of this callback should be aware that
@@ -511,7 +550,13 @@
}
/**
- * Callback invoked when connection state changes.
+ * Callback invoked when connection state changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
* @see TelephonyManager#DATA_DISCONNECTED
* @see TelephonyManager#DATA_CONNECTING
@@ -529,7 +574,13 @@
}
/**
- * Callback invoked when data activity state changes.
+ * Callback invoked when data activity state changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
* @see TelephonyManager#DATA_ACTIVITY_NONE
* @see TelephonyManager#DATA_ACTIVITY_IN
@@ -542,12 +593,13 @@
}
/**
- * Callback invoked when network signal strengths changes.
- *
- * @see ServiceState#STATE_EMERGENCY_ONLY
- * @see ServiceState#STATE_IN_SERVICE
- * @see ServiceState#STATE_OUT_OF_SERVICE
- * @see ServiceState#STATE_POWER_OFF
+ * Callback invoked when network signal strengths changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
*/
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
// default implementation empty
@@ -555,8 +607,15 @@
/**
- * The Over The Air Service Provisioning (OTASP) has changed. Requires
- * the READ_PHONE_STATE permission.
+ * The Over The Air Service Provisioning (OTASP) has changed on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
+ * Requires the READ_PHONE_STATE permission.
* @param otaspMode is integer <code>OTASP_UNKNOWN=1<code>
* means the value is currently unknown and the system should wait until
* <code>OTASP_NEEDED=2<code> or <code>OTASP_NOT_NEEDED=3<code> is received before
@@ -570,15 +629,28 @@
}
/**
- * Callback invoked when a observed cell info has changed,
- * or new cells have been added or removed.
+ * Callback invoked when a observed cell info has changed or new cells have been added
+ * or removed on the registered subscription.
+ * Note, the registration subId s from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
* @param cellInfo is the list of currently visible cells.
*/
public void onCellInfoChanged(List<CellInfo> cellInfo) {
}
/**
- * Callback invoked when precise device call state changes.
+ * Callback invoked when precise device call state changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
* @param callState {@link PreciseCallState}
* @hide
*/
@@ -589,7 +661,14 @@
}
/**
- * Callback invoked when call disconnect cause changes.
+ * Callback invoked when call disconnect cause changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
* @param disconnectCause {@link DisconnectCause}.
* @param preciseDisconnectCause {@link PreciseDisconnectCause}.
*
@@ -602,7 +681,14 @@
}
/**
- * Callback invoked when Ims call disconnect cause changes.
+ * Callback invoked when Ims call disconnect cause changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
* @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed.
*
* @hide
@@ -614,7 +700,15 @@
}
/**
- * Callback invoked when data connection state changes with precise information.
+ * Callback invoked when data connection state changes with precise information
+ * on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
* @param dataConnectionState {@link PreciseDataConnectionState}
*
* @hide
@@ -627,7 +721,13 @@
}
/**
- * Callback invoked when data connection state changes with precise information.
+ * Callback invoked when data connection real time info changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
* @hide
*/
@@ -639,7 +739,15 @@
/**
* Callback invoked when there has been a change in the Single Radio Voice Call Continuity
- * (SRVCC) state for the currently active call.
+ * (SRVCC) state for the currently active call on the registered subscription.
+ *
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
* @hide
*/
@SystemApi
@@ -648,7 +756,15 @@
}
/**
- * Callback invoked when the SIM voice activation state has changed
+ * Callback invoked when the SIM voice activation state has changed on the registered
+ * subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
* @param state is the current SIM voice activation state
* @hide
*/
@@ -657,7 +773,15 @@
}
/**
- * Callback invoked when the SIM data activation state has changed
+ * Callback invoked when the SIM data activation state has changed on the registered
+ * subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
* @param state is the current SIM data activation state
* @hide
*/
@@ -665,7 +789,14 @@
}
/**
- * Callback invoked when the user mobile data state has changed
+ * Callback invoked when the user mobile data state has changed on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
* @param enabled indicates whether the current user mobile data state is enabled or disabled.
*/
public void onUserMobileDataStateChanged(boolean enabled) {
@@ -673,7 +804,14 @@
}
/**
- * Callback invoked when the current physical channel configuration has changed
+ * Callback invoked when the current physical channel configuration has changed on the
+ * registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
* @param configs List of the current {@link PhysicalChannelConfig}s
* @hide
@@ -684,7 +822,14 @@
}
/**
- * Callback invoked when the current emergency number list has changed
+ * Callback invoked when the current emergency number list has changed on the registered
+ * subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
* @param emergencyNumberList Map including the key as the active subscription ID
* (Note: if there is no active subscription, the key is
@@ -699,8 +844,15 @@
}
/**
- * Callback invoked when OEM hook raw event is received. Requires
- * the READ_PRIVILEGED_PHONE_STATE permission.
+ * Callback invoked when OEM hook raw event is received on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
+ * Requires the READ_PRIVILEGED_PHONE_STATE permission.
* @param rawData is the byte array of the OEM hook raw data.
* @hide
*/
@@ -710,8 +862,10 @@
}
/**
- * Callback invoked when phone capability changes. Requires
- * the READ_PRIVILEGED_PHONE_STATE permission.
+ * Callback invoked when phone capability changes.
+ * Note, this callback triggers regardless of registered subscription.
+ *
+ * Requires the READ_PRIVILEGED_PHONE_STATE permission.
* @param capability the new phone capability
* @hide
*/
@@ -720,8 +874,10 @@
}
/**
- * Callback invoked when active data subId changes. Requires
- * the READ_PHONE_STATE permission.
+ * Callback invoked when active data subId changes.
+ * Note, this callback triggers regardless of registered subscription.
+ *
+ * Requires the READ_PHONE_STATE permission.
* @param subId current subscription used to setup Cellular Internet data.
* For example, it could be the current active opportunistic subscription in use,
* or the subscription user selected as default data subscription in DSDS mode.
@@ -731,8 +887,15 @@
}
/**
- * Callback invoked when the call attributes changes. Requires
- * the READ_PRIVILEGED_PHONE_STATE permission.
+ * Callback invoked when the call attributes changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
+ * Requires the READ_PRIVILEGED_PHONE_STATE permission.
* @param callAttributes the call attributes
* @hide
*/
@@ -742,7 +905,15 @@
}
/**
- * Callback invoked when modem radio power state changes. Requires
+ * Callback invoked when modem radio power state changes on the registered subscription.
+ * Note, the registration subId comes from {@link TelephonyManager} object which registers
+ * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subId. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
+ * Requires
* the READ_PRIVILEGED_PHONE_STATE permission.
* @param state the modem radio power state
* @hide
@@ -758,6 +929,10 @@
* has been requested by an app using
* {@link android.telephony.TelephonyManager#notifyCarrierNetworkChange(boolean)}
*
+ * Note, this callback is pinned to the registered subscription and will be invoked when
+ * the notifying carrier app has carrier privilege rule on the registered
+ * subscription. {@link android.telephony.TelephonyManager#hasCarrierPrivileges}
+ *
* @param active Whether the carrier network change is or shortly
* will be active. This value is true to indicate
* showing alternative UI and false to stop.
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 63d427a..8c20afe 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -27,10 +27,10 @@
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.PendingIntent;
-import android.content.ActivityNotFoundException;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.database.CursorWindow;
import android.net.Uri;
import android.os.BaseBundle;
@@ -39,12 +39,15 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.provider.Telephony;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.IMms;
import com.android.internal.telephony.ISms;
+import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.SmsRawData;
import java.lang.annotation.Retention;
@@ -64,22 +67,22 @@
/**
* Manages SMS operations such as sending data, text, and pdu SMS messages.
- * Get this object by calling the static method {@link #getDefault()}.
+ * Get this object by calling the static method {@link #getDefault()}. To create an instance of
+ * {@link SmsManager} associated with a specific subscription ID, call
+ * {@link #getSmsManagerForSubscriptionId(int)}. This is typically used for devices that support
+ * multiple active subscriptions at once.
*
* <p>For information about how to behave as the default SMS app on Android 4.4 (API level 19)
* and higher, see {@link android.provider.Telephony}.
+ *
+ * @see SubscriptionManager#getActiveSubscriptionInfoList()
*/
public final class SmsManager {
private static final String TAG = "SmsManager";
- /**
- * A psuedo-subId that represents the default subId at any given time. The actual subId it
- * represents changes as the default subId is changed.
- */
- private static final int DEFAULT_SUBSCRIPTION_ID = -1002;
-
/** Singleton object constructed during class initialization. */
- private static final SmsManager sInstance = new SmsManager(DEFAULT_SUBSCRIPTION_ID);
+ private static final SmsManager sInstance = new SmsManager(
+ SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
private static final Object sLockObject = new Object();
/** @hide */
@@ -120,7 +123,7 @@
* Whether MMS is enabled for the current carrier (boolean type)
*/
public static final String
- MMS_CONFIG_MMS_ENABLED = CarrierConfigManager.KEY_MMS_MMS_ENABLED_BOOL;
+ MMS_CONFIG_MMS_ENABLED = CarrierConfigManager.KEY_MMS_MMS_ENABLED_BOOL;
/**
* Whether group MMS is enabled for the current carrier (boolean type)
*/
@@ -279,12 +282,6 @@
public static final String MMS_CONFIG_CLOSE_CONNECTION =
CarrierConfigManager.KEY_MMS_CLOSE_CONNECTION_BOOL;
- /*
- * Forwarded constants from SimDialogActivity.
- */
- private static String DIALOG_TYPE_KEY = "dialog_type";
- private static final int SMS_PICK = 2;
-
/**
* 3gpp2 SMS priority is not specified
* @hide
@@ -297,6 +294,18 @@
public static final int SMS_MESSAGE_PERIOD_NOT_SPECIFIED = -1;
/**
+ * Extra key passed into a PendingIntent when the SMS operation failed due to there being no
+ * default set.
+ */
+ private static final String NO_DEFAULT_EXTRA = "noDefault";
+
+ // result of asking the user for a subscription to perform an operation.
+ private interface SubscriptionResolverResult {
+ void onSuccess(int subId);
+ void onFailure();
+ }
+
+ /**
* Send a text based SMS.
*
* <p class="note"><strong>Note:</strong> Using this method requires that your app has the
@@ -308,6 +317,15 @@
* responsible for writing its sent messages to the SMS Provider). For information about
* how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
*
+ * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+ * manager on a multi-SIM device, this operation may fail sending the SMS message because no
+ * suitable default subscription could be found. In this case, if {@code sentIntent} is
+ * non-null, then the {@link PendingIntent} will be sent with an error code
+ * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
+ * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
+ * where this operation may fail.
+ * </p>
+ *
*
* @param destinationAddress the address to send the message to
* @param scAddress is the service center address or null to use
@@ -337,12 +355,12 @@
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
- true /* persistMessage*/);
+ true /* persistMessage*/, ActivityThread.currentPackageName());
}
private void sendTextMessageInternal(String destinationAddress, String scAddress,
String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
- boolean persistMessage) {
+ boolean persistMessage, String packageName) {
if (TextUtils.isEmpty(destinationAddress)) {
throw new IllegalArgumentException("Invalid destinationAddress");
}
@@ -351,16 +369,51 @@
throw new IllegalArgumentException("Invalid message body");
}
- try {
- // If the subscription is invalid or default, we will use the default phone to send the
- // SMS and possibly fail later in the SMS sending process.
+ final Context context = ActivityThread.currentApplication().getApplicationContext();
+ // We will only show the SMS disambiguation dialog in the case that the message is being
+ // persisted. This is for two reasons:
+ // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
+ // subscription and require special permissions. These messages are usually not sent by
+ // the device user and should not have an SMS disambiguation dialog associated with them
+ // because the device user did not trigger them.
+ // 2) The SMS disambiguation dialog ONLY checks to make sure that the user has the SEND_SMS
+ // permission. If we call resolveSubscriptionForOperation from a carrier/OEM app that has
+ // the correct MODIFY_PHONE_STATE or carrier permissions, but no SEND_SMS, it will throw
+ // an incorrect SecurityException.
+ if (persistMessage) {
+ resolveSubscriptionForOperation(new SubscriptionResolverResult() {
+ @Override
+ public void onSuccess(int subId) {
+ ISms iSms = getISmsServiceOrThrow();
+ try {
+ iSms.sendTextForSubscriber(subId, packageName,
+ destinationAddress, scAddress, text, sentIntent, deliveryIntent,
+ persistMessage);
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendTextMessageInternal: Couldn't send SMS, exception - "
+ + e.getMessage());
+ notifySmsGenericError(sentIntent);
+ }
+ }
+
+ @Override
+ public void onFailure() {
+ notifySmsErrorNoDefaultSet(context, sentIntent);
+ }
+ });
+ } else {
+ // Not persisting the message, used by sendTextMessageWithoutPersisting() and is not
+ // visible to the user.
ISms iSms = getISmsServiceOrThrow();
- iSms.sendTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(),
- destinationAddress,
- scAddress, text, sentIntent, deliveryIntent,
- persistMessage);
- } catch (RemoteException ex) {
- // ignore it
+ try {
+ iSms.sendTextForSubscriber(getSubscriptionId(), packageName,
+ destinationAddress, scAddress, text, sentIntent, deliveryIntent,
+ persistMessage);
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendTextMessageInternal (no persist): Couldn't send SMS, exception - "
+ + e.getMessage());
+ notifySmsGenericError(sentIntent);
+ }
}
}
@@ -377,6 +430,17 @@
* privileges (see {@link TelephonyManager#hasCarrierPrivileges}), or that the calling app is
* the default IMS app (see
* {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}).
+ * </p>
+ *
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the SMS being sent on the subscription associated with logical
+ * slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the
+ * correct subscription.
+ * </p>
*
* @see #sendTextMessage(String, String, String, PendingIntent, PendingIntent)
*/
@@ -389,13 +453,23 @@
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
- false /* persistMessage */);
+ false /* persistMessage */, ActivityThread.currentPackageName());
}
/**
* A variant of {@link SmsManager#sendTextMessage} that allows self to be the caller. This is
* for internal use only.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the SMS being sent on the subscription associated with logical
+ * slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the
+ * correct subscription.
+ * </p>
+ *
* @param persistMessage whether to persist the sent message in the SMS app. the caller must be
* the Phone process if set to false.
*
@@ -419,13 +493,22 @@
destinationAddress,
scAddress, text, sentIntent, deliveryIntent, persistMessage);
} catch (RemoteException ex) {
- // ignore it
+ notifySmsGenericError(sentIntent);
}
}
/**
* Send a text based SMS with messaging options.
*
+ * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+ * manager on a multi-SIM device, this operation may fail sending the SMS message because no
+ * suitable default subscription could be found. In this case, if {@code sentIntent} is
+ * non-null, then the {@link PendingIntent} will be sent with an error code
+ * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
+ * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
+ * where this operation may fail.
+ * </p>
+ *
* @param destinationAddress the address to send the message to
* @param scAddress is the service center address or null to use
* the current default SMSC
@@ -496,16 +579,59 @@
validityPeriod = SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
}
- try {
- ISms iSms = getISmsServiceOrThrow();
- if (iSms != null) {
- iSms.sendTextForSubscriberWithOptions(getSubscriptionId(),
- ActivityThread.currentPackageName(), destinationAddress, scAddress, text,
- sentIntent, deliveryIntent, persistMessage, priority, expectMore,
- validityPeriod);
+ final int finalPriority = priority;
+ final int finalValidity = validityPeriod;
+ final Context context = ActivityThread.currentApplication().getApplicationContext();
+ // We will only show the SMS disambiguation dialog in the case that the message is being
+ // persisted. This is for two reasons:
+ // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
+ // subscription and require special permissions. These messages are usually not sent by
+ // the device user and should not have an SMS disambiguation dialog associated with them
+ // because the device user did not trigger them.
+ // 2) The SMS disambiguation dialog ONLY checks to make sure that the user has the SEND_SMS
+ // permission. If we call resolveSubscriptionForOperation from a carrier/OEM app that has
+ // the correct MODIFY_PHONE_STATE or carrier permissions, but no SEND_SMS, it will throw
+ // an incorrect SecurityException.
+ if (persistMessage) {
+ resolveSubscriptionForOperation(new SubscriptionResolverResult() {
+ @Override
+ public void onSuccess(int subId) {
+ try {
+ ISms iSms = getISmsServiceOrThrow();
+ if (iSms != null) {
+ iSms.sendTextForSubscriberWithOptions(subId,
+ ActivityThread.currentPackageName(), destinationAddress,
+ scAddress,
+ text, sentIntent, deliveryIntent, persistMessage, finalPriority,
+ expectMore, finalValidity);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendTextMessageInternal: Couldn't send SMS, exception - "
+ + e.getMessage());
+ notifySmsGenericError(sentIntent);
+ }
+ }
+
+ @Override
+ public void onFailure() {
+ notifySmsErrorNoDefaultSet(context, sentIntent);
+ }
+ });
+ } else {
+ try {
+ ISms iSms = getISmsServiceOrThrow();
+ if (iSms != null) {
+ iSms.sendTextForSubscriberWithOptions(getSubscriptionId(),
+ ActivityThread.currentPackageName(), destinationAddress,
+ scAddress,
+ text, sentIntent, deliveryIntent, persistMessage, finalPriority,
+ expectMore, finalValidity);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendTextMessageInternal(no persist): Couldn't send SMS, exception - "
+ + e.getMessage());
+ notifySmsGenericError(sentIntent);
}
- } catch (RemoteException ex) {
- // ignore it
}
}
@@ -517,6 +643,16 @@
* privileges.
* </p>
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the SMS being sent on the subscription associated with logical
+ * slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the
+ * correct subscription.
+ * </p>
+ *
* @see #sendTextMessage(String, String, String, PendingIntent,
* PendingIntent, int, boolean, int)
* @hide
@@ -537,6 +673,16 @@
* <p>Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier
* privileges per {@link android.telephony.TelephonyManager#hasCarrierPrivileges}.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the SMS being injected on the subscription associated with
+ * logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is
+ * delivered to the correct subscription.
+ * </p>
+ *
* @param pdu is the byte array of pdu to be injected into android application framework
* @param format is the format of SMS pdu ({@link SmsMessage#FORMAT_3GPP} or
* {@link SmsMessage#FORMAT_3GPP2})
@@ -564,7 +710,13 @@
getSubscriptionId(), pdu, format, receivedIntent);
}
} catch (RemoteException ex) {
- // ignore it
+ try {
+ if (receivedIntent != null) {
+ receivedIntent.send(Telephony.Sms.Intents.RESULT_SMS_GENERIC_ERROR);
+ }
+ } catch (PendingIntent.CanceledException cx) {
+ // Don't worry about it, we do not need to notify the caller if this is the case.
+ }
}
}
@@ -599,6 +751,16 @@
* responsible for writing its sent messages to the SMS Provider). For information about
* how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
*
+ * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+ * manager on a multi-SIM device, this operation may fail sending the SMS message because no
+ * suitable default subscription could be found. In this case, if {@code sentIntent} is
+ * non-null, then the {@link PendingIntent} will be sent with an error code
+ * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
+ * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
+ * where this operation may fail.
+ * </p>
+ *
+ *
* @param destinationAddress the address to send the message to
* @param scAddress is the service center address or null to use
* the current default SMSC
@@ -630,13 +792,41 @@
String destinationAddress, String scAddress, ArrayList<String> parts,
ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
- deliveryIntents, true /* persistMessage*/);
+ deliveryIntents, true /* persistMessage*/, ActivityThread.currentPackageName());
+ }
+
+ /**
+ * Similar method as #sendMultipartTextMessage(String, String, ArrayList, ArrayList, ArrayList)
+ * With an additional argument.
+ *
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use the Telephony
+ * framework and will never trigger an SMS disambiguation dialog. If this method is called on a
+ * device that has multiple active subscriptions, this {@link SmsManager} instance has been
+ * created with {@link #getDefault()}, and no user-defined default subscription is defined, the
+ * subscription ID associated with this message will be INVALID, which will result in the SMS
+ * being sent on the subscription associated with logical slot 0. Use
+ * {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the correct
+ * subscription.
+ * </p>
+ *
+ * @param packageName serves as the default package name if
+ * {@link ActivityThread#currentPackageName()} is null.
+ * @hide
+ */
+ public void sendMultipartTextMessageExternal(
+ String destinationAddress, String scAddress, ArrayList<String> parts,
+ ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
+ String packageName) {
+ sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
+ deliveryIntents, true /* persistMessage*/,
+ ActivityThread.currentPackageName() == null
+ ? packageName : ActivityThread.currentPackageName());
}
private void sendMultipartTextMessageInternal(
String destinationAddress, String scAddress, List<String> parts,
List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents,
- boolean persistMessage) {
+ boolean persistMessage, String packageName) {
if (TextUtils.isEmpty(destinationAddress)) {
throw new IllegalArgumentException("Invalid destinationAddress");
}
@@ -645,14 +835,52 @@
}
if (parts.size() > 1) {
- try {
- ISms iSms = getISmsServiceOrThrow();
- iSms.sendMultipartTextForSubscriber(getSubscriptionId(),
- ActivityThread.currentPackageName(),
- destinationAddress, scAddress, parts,
- sentIntents, deliveryIntents, persistMessage);
- } catch (RemoteException ex) {
- // ignore it
+ final Context context = ActivityThread.currentApplication().getApplicationContext();
+ // We will only show the SMS disambiguation dialog in the case that the message is being
+ // persisted. This is for two reasons:
+ // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
+ // subscription and require special permissions. These messages are usually not sent
+ // by the device user and should not have an SMS disambiguation dialog associated
+ // with them because the device user did not trigger them.
+ // 2) The SMS disambiguation dialog ONLY checks to make sure that the user has the
+ // SEND_SMS permission. If we call resolveSubscriptionForOperation from a carrier/OEM
+ // app that has the correct MODIFY_PHONE_STATE or carrier permissions, but no
+ // SEND_SMS, it will throw an incorrect SecurityException.
+ if (persistMessage) {
+ resolveSubscriptionForOperation(new SubscriptionResolverResult() {
+ @Override
+ public void onSuccess(int subId) {
+ try {
+ ISms iSms = getISmsServiceOrThrow();
+ iSms.sendMultipartTextForSubscriber(subId, packageName,
+ destinationAddress, scAddress, parts, sentIntents,
+ deliveryIntents, persistMessage);
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - "
+ + e.getMessage());
+ notifySmsGenericError(sentIntents);
+ }
+ }
+
+ @Override
+ public void onFailure() {
+ notifySmsErrorNoDefaultSet(context, sentIntents);
+ }
+ });
+ } else {
+ // Called by apps that are not user facing, don't show disambiguation dialog.
+ try {
+ ISms iSms = getISmsServiceOrThrow();
+ if (iSms != null) {
+ iSms.sendMultipartTextForSubscriber(getSubscriptionId(), packageName,
+ destinationAddress, scAddress, parts, sentIntents, deliveryIntents,
+ persistMessage);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - "
+ + e.getMessage());
+ notifySmsGenericError(sentIntents);
+ }
}
} else {
PendingIntent sentIntent = null;
@@ -663,14 +891,23 @@
if (deliveryIntents != null && deliveryIntents.size() > 0) {
deliveryIntent = deliveryIntents.get(0);
}
- sendTextMessage(destinationAddress, scAddress, parts.get(0),
- sentIntent, deliveryIntent);
+ sendTextMessageInternal(destinationAddress, scAddress, parts.get(0),
+ sentIntent, deliveryIntent, true, packageName);
}
}
/**
* Send a multi-part text based SMS without writing it into the SMS Provider.
*
+ * <p>
+ * If this method is called on a device with multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the SMS sent on the subscription associated with slot
+ * 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent using the
+ * correct subscription.
+ * </p>
+ *
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier
* privileges.
@@ -685,7 +922,7 @@
String destinationAddress, String scAddress, List<String> parts,
List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
- deliveryIntents, false /* persistMessage*/);
+ deliveryIntents, false /* persistMessage*/, ActivityThread.currentPackageName());
}
/**
@@ -702,6 +939,15 @@
* responsible for writing its sent messages to the SMS Provider). For information about
* how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
*
+ * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+ * manager on a multi-SIM device, this operation may fail sending the SMS message because no
+ * suitable default subscription could be found. In this case, if {@code sentIntent} is
+ * non-null, then the {@link PendingIntent} will be sent with an error code
+ * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
+ * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
+ * where this operation may fail.
+ * </p>
+
* @param destinationAddress the address to send the message to
* @param scAddress is the service center address or null to use
* the current default SMSC
@@ -769,24 +1015,56 @@
}
if (priority < 0x00 || priority > 0x03) {
- priority = SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
+ priority = SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
}
if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) {
- validityPeriod = SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
+ validityPeriod = SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
}
if (parts.size() > 1) {
- try {
- ISms iSms = getISmsServiceOrThrow();
- if (iSms != null) {
- iSms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(),
- ActivityThread.currentPackageName(), destinationAddress, scAddress,
- parts, sentIntents, deliveryIntents, persistMessage, priority,
- expectMore, validityPeriod);
+ final int finalPriority = priority;
+ final int finalValidity = validityPeriod;
+ final Context context = ActivityThread.currentApplication().getApplicationContext();
+ if (persistMessage) {
+ resolveSubscriptionForOperation(new SubscriptionResolverResult() {
+ @Override
+ public void onSuccess(int subId) {
+ try {
+ ISms iSms = getISmsServiceOrThrow();
+ if (iSms != null) {
+ iSms.sendMultipartTextForSubscriberWithOptions(subId,
+ ActivityThread.currentPackageName(), destinationAddress,
+ scAddress, parts, sentIntents, deliveryIntents,
+ persistMessage, finalPriority, expectMore, finalValidity);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - "
+ + e.getMessage());
+ notifySmsGenericError(sentIntents);
+ }
+ }
+
+ @Override
+ public void onFailure() {
+ notifySmsErrorNoDefaultSet(context, sentIntents);
+ }
+ });
+ } else {
+ // Sent by apps that are not user visible, so don't show SIM disambiguation dialog.
+ try {
+ ISms iSms = getISmsServiceOrThrow();
+ if (iSms != null) {
+ iSms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(),
+ ActivityThread.currentPackageName(), destinationAddress,
+ scAddress, parts, sentIntents, deliveryIntents,
+ persistMessage, finalPriority, expectMore, finalValidity);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendMultipartTextMessageInternal (no persist): Couldn't send SMS - "
+ + e.getMessage());
+ notifySmsGenericError(sentIntents);
}
- } catch (RemoteException ex) {
- // ignore it
}
} else {
PendingIntent sentIntent = null;
@@ -811,6 +1089,16 @@
* privileges.
* </p>
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use the Telephony
+ * framework and will never trigger an SMS disambiguation dialog. If this method is called on a
+ * device that has multiple active subscriptions, this {@link SmsManager} instance has been
+ * created with {@link #getDefault()}, and no user-defined default subscription is defined, the
+ * subscription ID associated with this message will be INVALID, which will result in the SMS
+ * being sent on the subscription associated with logical slot 0. Use
+ * {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the correct
+ * subscription.
+ * </p>
+ *
* @see #sendMultipartTextMessage(String, String, ArrayList, ArrayList,
* ArrayList, int, boolean, int)
* @hide
@@ -824,12 +1112,21 @@
validityPeriod);
}
- /**
+ /**
* Send a data based SMS to a specific application port.
*
* <p class="note"><strong>Note:</strong> Using this method requires that your app has the
* {@link android.Manifest.permission#SEND_SMS} permission.</p>
*
+ * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+ * manager on a multi-SIM device, this operation may fail sending the SMS message because no
+ * suitable default subscription could be found. In this case, if {@code sentIntent} is
+ * non-null, then the {@link PendingIntent} will be sent with an error code
+ * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
+ * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
+ * where this operation may fail.
+ * </p>
+ *
* @param destinationAddress the address to send the message to
* @param scAddress is the service center address or null to use
* the current default SMSC
@@ -865,20 +1162,41 @@
throw new IllegalArgumentException("Invalid message data");
}
- try {
- ISms iSms = getISmsServiceOrThrow();
- iSms.sendDataForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(),
- destinationAddress, scAddress, destinationPort & 0xFFFF,
- data, sentIntent, deliveryIntent);
- } catch (RemoteException ex) {
- // ignore it
- }
+ final Context context = ActivityThread.currentApplication().getApplicationContext();
+ resolveSubscriptionForOperation(new SubscriptionResolverResult() {
+ @Override
+ public void onSuccess(int subId) {
+ try {
+ ISms iSms = getISmsServiceOrThrow();
+ iSms.sendDataForSubscriber(subId, ActivityThread.currentPackageName(),
+ destinationAddress, scAddress, destinationPort & 0xFFFF, data,
+ sentIntent, deliveryIntent);
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendDataMessage: Couldn't send SMS - Exception: " + e.getMessage());
+ notifySmsGenericError(sentIntent);
+ }
+ }
+ @Override
+ public void onFailure() {
+ notifySmsErrorNoDefaultSet(context, sentIntent);
+ }
+ });
}
/**
* A variant of {@link SmsManager#sendDataMessage} that allows self to be the caller. This is
* for internal use only.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the SMS being sent on the subscription associated with logical
+ * slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the SMS is sent on the
+ * correct subscription.
+ * </p>
+ *
* @hide
*/
public void sendDataMessageWithSelfPermissions(
@@ -897,30 +1215,63 @@
iSms.sendDataForSubscriberWithSelfPermissions(getSubscriptionId(),
ActivityThread.currentPackageName(), destinationAddress, scAddress,
destinationPort & 0xFFFF, data, sentIntent, deliveryIntent);
- } catch (RemoteException ex) {
- // ignore it
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendDataMessageWithSelfPermissions: Couldn't send SMS - Exception: "
+ + e.getMessage());
+ notifySmsGenericError(sentIntent);
}
}
/**
* Get the SmsManager associated with the default subscription id. The instance will always be
- * associated with the default subscription id, even if the default subscription id is changed.
+ * associated with the default subscription id, even if the default subscription id changes.
*
- * @return the SmsManager associated with the default subscription id
+ * <p class="note"><strong>Note:</strong> For devices that support multiple active subscriptions
+ * at a time, SmsManager will track the subscription set by the user as the default SMS
+ * subscription. If the user has not set a default, {@link SmsManager} may
+ * start an activity to kick off a subscription disambiguation dialog. Most operations will not
+ * complete until the user has chosen the subscription that will be associated with the
+ * operation. If the user cancels the dialog without choosing a subscription, one of the
+ * following will happen, depending on the target SDK version of the application. For
+ * compatibility purposes, if the target SDK level is <= 28, telephony will still send the SMS
+ * over the first available subscription. If the target SDK level is > 28, the operation will
+ * fail to complete.
+ * </p>
+ *
+ * <p class="note"><strong>Note:</strong> If this method is used to perform an operation on a
+ * device that has multiple active subscriptions, the user has not set a default SMS
+ * subscription, and the operation is being performed while the application is not in the
+ * foreground, the SMS disambiguation dialog will not be shown. The result of the operation will
+ * conclude as if the user cancelled the disambiguation dialog and the operation will finish as
+ * outlined above, depending on the target SDK version of the calling application. It is safer
+ * to use {@link #getSmsManagerForSubscriptionId(int)} if the application will perform the
+ * operation while in the background because this can cause unpredictable results, such as the
+ * operation being sent over the wrong subscription or failing completely, depending on the
+ * user's default SMS subscription setting.
+ * </p>
+ *
+ * @return the {@link SmsManager} associated with the default subscription id.
+ *
+ * @see SubscriptionManager#getDefaultSmsSubscriptionId()
*/
public static SmsManager getDefault() {
return sInstance;
}
/**
- * Get the the instance of the SmsManager associated with a particular subscription id
+ * Get the instance of the SmsManager associated with a particular subscription ID.
*
- * @param subId an SMS subscription id, typically accessed using
- * {@link android.telephony.SubscriptionManager}
- * @return the instance of the SmsManager associated with subId
+ * <p class="note"><strong>Note:</strong> Constructing an {@link SmsManager} in this manner will
+ * never cause an SMS disambiguation dialog to appear, unlike {@link #getDefault()}.
+ * </p>
+ *
+ * @param subId an SMS subscription ID, typically accessed using {@link SubscriptionManager}
+ * @return the instance of the SmsManager associated with subscription
+ *
+ * @see SubscriptionManager#getActiveSubscriptionInfoList()
+ * @see SubscriptionManager#getDefaultSmsSubscriptionId()
*/
public static SmsManager getSmsManagerForSubscriptionId(int subId) {
- // TODO(shri): Add javadoc link once SubscriptionManager is made public api
synchronized(sLockObject) {
SmsManager smsManager = sSubInstances.get(subId);
if (smsManager == null) {
@@ -938,60 +1289,188 @@
/**
* Get the associated subscription id. If the instance was returned by {@link #getDefault()},
* then this method may return different values at different points in time (if the user
- * changes the default subscription id). It will return < 0 if the default subscription id
- * cannot be determined.
+ * changes the default subscription id).
*
- * Additionally, to support legacy applications that are not multi-SIM aware,
- * if the following are true:
- * - We are using a multi-SIM device
- * - A default SMS SIM has not been selected
- * - At least one SIM subscription is available
- * then ask the user to set the default SMS SIM.
+ * <p class="note"><strong>Note:</strong> This method used to display a disambiguation dialog to
+ * the user asking them to choose a default subscription to send SMS messages over if they
+ * haven't chosen yet. Starting in API level 29, we allow the user to not have a default set as
+ * a valid option for the default SMS subscription on multi-SIM devices. We no longer show the
+ * disambiguation dialog and return {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if the
+ * device has multiple active subscriptions and no default is set.
+ * </p>
*
- * @return associated subscription id
+ * @return associated subscription ID or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if
+ * the default subscription id cannot be determined or the device has multiple active
+ * subscriptions and and no default is set ("ask every time") by the user.
*/
public int getSubscriptionId() {
- final int subId = getSubIdOrDefault();
+ try {
+ return (mSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
+ ? getISmsServiceOrThrow().getPreferredSmsSubscription() : mSubId;
+ } catch (RemoteException e) {
+ return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+ }
+
+ /**
+ * Resolves the subscription id to use for the associated operation if
+ * {@link #getSubscriptionId()} returns {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
+ *
+ * If app targets API level 28 or below and they are either sending the SMS from the background
+ * or the device has more than one active subscription available and no default is set, we will
+ * use the first logical slot to send the SMS and possibly fail later in the SMS sending
+ * process.
+ *
+ * Regardless of the API level, if the app is the foreground app, then we will show the SMS
+ * disambiguation dialog. If the app is in the background and tries to perform an operation, we
+ * will not show the disambiguation dialog.
+ *
+ * See {@link #getDefault()} for a detailed explanation of how this method operates.
+ *
+ * @param resolverResult The callback that will be called when the subscription is resolved or
+ * fails to be resolved.
+ */
+ private void resolveSubscriptionForOperation(SubscriptionResolverResult resolverResult) {
+ int subId = getSubscriptionId();
boolean isSmsSimPickActivityNeeded = false;
final Context context = ActivityThread.currentApplication().getApplicationContext();
try {
ISms iSms = getISmsService();
if (iSms != null) {
+ // Determines if the SMS SIM pick activity should be shown. This is only shown if:
+ // 1) The device has multiple active subscriptions and an SMS default subscription
+ // hasn't been set, and
+ // 2) SmsManager is being called from the foreground app.
+ // Android does not allow background activity starts, so we need to block this.
+ // if Q+, do not perform requested operation if these two operations are not set. If
+ // <P, perform these operations on phone 0 (for compatibility purposes, since we
+ // used to not wait for the result of this activity).
isSmsSimPickActivityNeeded = iSms.isSmsSimPickActivityNeeded(subId);
}
} catch (RemoteException ex) {
- Log.e(TAG, "Exception in getSubscriptionId");
+ Log.e(TAG, "resolveSubscriptionForOperation", ex);
}
-
- if (isSmsSimPickActivityNeeded) {
- Log.d(TAG, "getSubscriptionId isSmsSimPickActivityNeeded is true");
- // ask the user for a default SMS SIM.
- Intent intent = new Intent();
- intent.setClassName("com.android.settings",
- "com.android.settings.sim.SimDialogActivity");
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(DIALOG_TYPE_KEY, SMS_PICK);
- try {
- context.startActivity(intent);
- } catch (ActivityNotFoundException anfe) {
- // If Settings is not installed, only log the error as we do not want to break
- // legacy applications.
- Log.e(TAG, "Unable to launch Settings application.");
- }
+ if (!isSmsSimPickActivityNeeded) {
+ sendResolverResult(resolverResult, subId, false /*pickActivityShown*/);
+ return;
}
-
- return subId;
+ // We need to ask the user pick an appropriate subid for the operation.
+ Log.d(TAG, "resolveSubscriptionForOperation isSmsSimPickActivityNeeded is true for package "
+ + context.getPackageName());
+ try {
+ // Create the SMS pick activity and call back once the activity is complete. Can't do
+ // it here because we do not have access to the activity context that is performing this
+ // operation.
+ // Requires that the calling process has the SEND_SMS permission.
+ getITelephony().enqueueSmsPickResult(context.getOpPackageName(),
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int subId) {
+ // Runs on binder thread attached to this app's process.
+ sendResolverResult(resolverResult, subId, true /*pickActivityShown*/);
+ }
+ });
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to launch activity", ex);
+ // pickActivityShown is true here because we want to call sendResolverResult and always
+ // have this operation fail. This is because we received a RemoteException here, which
+ // means that telephony is not available and the next operation to Telephony will fail
+ // as well anyways, so we might as well shortcut fail here first.
+ sendResolverResult(resolverResult, subId, true /*pickActivityShown*/);
+ }
}
- /**
- * @return the subscription ID associated with this {@link SmsManager} or the default set by the
- * user if this instance was created using {@link SmsManager#getDefault}.
- *
- * If there is no default set by the user, this method returns
- * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
- */
- private int getSubIdOrDefault() {
- return (mSubId == DEFAULT_SUBSCRIPTION_ID) ? getDefaultSmsSubscriptionId() : mSubId;
+ private void sendResolverResult(SubscriptionResolverResult resolverResult, int subId,
+ boolean pickActivityShown) {
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ resolverResult.onSuccess(subId);
+ return;
+ }
+
+ if (getTargetSdkVersion() <= Build.VERSION_CODES.P && !pickActivityShown) {
+ // Do not fail, return a success with an INVALID subid for apps targeting P or below
+ // that tried to perform an operation and the SMS disambiguation dialog was never shown,
+ // as these applications may not have been written to handle the failure case properly.
+ // This will resolve to performing the operation on phone 0 in telephony.
+ resolverResult.onSuccess(subId);
+ } else {
+ // Fail if the app targets Q or above or it targets P and below and the disambiguation
+ // dialog was shown and the user clicked out of it.
+ resolverResult.onFailure();
+ }
+ }
+
+ private static int getTargetSdkVersion() {
+ final Context context = ActivityThread.currentApplication().getApplicationContext();
+ int targetSdk;
+ try {
+ targetSdk = context.getPackageManager().getApplicationInfo(
+ context.getOpPackageName(), 0).targetSdkVersion;
+ } catch (PackageManager.NameNotFoundException e) {
+ // Default to old behavior if we can not find this.
+ targetSdk = -1;
+ }
+ return targetSdk;
+ }
+
+ private static ITelephony getITelephony() {
+ ITelephony binder = ITelephony.Stub.asInterface(
+ ServiceManager.getService(Context.TELEPHONY_SERVICE));
+ if (binder == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+ return binder;
+ }
+
+ private static void notifySmsErrorNoDefaultSet(Context context, PendingIntent pendingIntent) {
+ if (pendingIntent != null) {
+ Intent errorMessage = new Intent();
+ errorMessage.putExtra(NO_DEFAULT_EXTRA, true);
+ try {
+ pendingIntent.send(context, RESULT_ERROR_GENERIC_FAILURE, errorMessage);
+ } catch (PendingIntent.CanceledException e) {
+ // Don't worry about it, we do not need to notify the caller if this is the case.
+ }
+ }
+ }
+
+ private static void notifySmsErrorNoDefaultSet(Context context,
+ List<PendingIntent> pendingIntents) {
+ if (pendingIntents != null) {
+ for (PendingIntent pendingIntent : pendingIntents) {
+ Intent errorMessage = new Intent();
+ errorMessage.putExtra(NO_DEFAULT_EXTRA, true);
+ try {
+ pendingIntent.send(context, RESULT_ERROR_GENERIC_FAILURE, errorMessage);
+ } catch (PendingIntent.CanceledException e) {
+ // Don't worry about it, we do not need to notify the caller if this is the
+ // case.
+ }
+ }
+ }
+ }
+
+ private static void notifySmsGenericError(PendingIntent pendingIntent) {
+ if (pendingIntent != null) {
+ try {
+ pendingIntent.send(RESULT_ERROR_GENERIC_FAILURE);
+ } catch (PendingIntent.CanceledException e) {
+ // Don't worry about it, we do not need to notify the caller if this is the case.
+ }
+ }
+ }
+
+ private static void notifySmsGenericError(List<PendingIntent> pendingIntents) {
+ if (pendingIntents != null) {
+ for (PendingIntent pendingIntent : pendingIntents) {
+ try {
+ pendingIntent.send(RESULT_ERROR_GENERIC_FAILURE);
+ } catch (PendingIntent.CanceledException e) {
+ // Don't worry about it, we do not need to notify the caller if this is the
+ // case.
+ }
+ }
+ }
}
/**
@@ -1015,6 +1494,16 @@
* ICC (Integrated Circuit Card) is the card of the device.
* For example, this can be the SIM or USIM for GSM.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param smsc the SMSC for this message, or NULL for the default SMSC
* @param pdu the raw PDU to store
* @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
@@ -1050,6 +1539,16 @@
* ICC (Integrated Circuit Card) is the card of the device.
* For example, this can be the SIM or USIM for GSM.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param messageIndex is the record index of the message on ICC
* @return true for success
*
@@ -1081,6 +1580,16 @@
* ICC (Integrated Circuit Card) is the card of the device.
* For example, this can be the SIM or USIM for GSM.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param messageIndex record index of message to update
* @param newStatus new message status (STATUS_ON_ICC_READ,
* STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
@@ -1113,6 +1622,16 @@
* ICC (Integrated Circuit Card) is the card of the device.
* For example, this can be the SIM or USIM for GSM.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @return <code>ArrayList</code> of <code>SmsMessage</code> objects
*
* {@hide}
@@ -1145,6 +1664,16 @@
* Note: This call is blocking, callers may want to avoid calling it from
* the main thread of an application.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP)
* or C.R1001-G (3GPP2)
* @param ranType as defined in class SmsManager, the value can be one of these:
@@ -1161,8 +1690,9 @@
try {
ISms iSms = getISmsService();
if (iSms != null) {
- // If getSubIdOrDefault() returns INVALID, we will use the default phone internally.
- success = iSms.enableCellBroadcastForSubscriber(getSubIdOrDefault(),
+ // If getSubscriptionId() returns INVALID or an inactive subscription, we will use
+ // the default phone internally.
+ success = iSms.enableCellBroadcastForSubscriber(getSubscriptionId(),
messageIdentifier, ranType);
}
} catch (RemoteException ex) {
@@ -1181,6 +1711,16 @@
* Note: This call is blocking, callers may want to avoid calling it from
* the main thread of an application.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP)
* or C.R1001-G (3GPP2)
* @param ranType as defined in class SmsManager, the value can be one of these:
@@ -1198,8 +1738,9 @@
try {
ISms iSms = getISmsService();
if (iSms != null) {
- // If getSubIdOrDefault() returns INVALID, we will use the default phone internally.
- success = iSms.disableCellBroadcastForSubscriber(getSubIdOrDefault(),
+ // If getSubscriptionId() returns INVALID or an inactive subscription, we will use
+ // the default phone internally.
+ success = iSms.disableCellBroadcastForSubscriber(getSubscriptionId(),
messageIdentifier, ranType);
}
} catch (RemoteException ex) {
@@ -1219,6 +1760,16 @@
* Note: This call is blocking, callers may want to avoid calling it from
* the main thread of an application.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param startMessageId first message identifier as specified in TS 23.041 (3GPP)
* or C.R1001-G (3GPP2)
* @param endMessageId last message identifier as specified in TS 23.041 (3GPP)
@@ -1242,8 +1793,9 @@
try {
ISms iSms = getISmsService();
if (iSms != null) {
- // If getSubIdOrDefault() returns INVALID, we will use the default phone internally.
- success = iSms.enableCellBroadcastRangeForSubscriber(getSubIdOrDefault(),
+ // If getSubscriptionId() returns INVALID or an inactive subscription, we will use
+ // the default phone internally.
+ success = iSms.enableCellBroadcastRangeForSubscriber(getSubscriptionId(),
startMessageId, endMessageId, ranType);
}
} catch (RemoteException ex) {
@@ -1262,6 +1814,16 @@
* Note: This call is blocking, callers may want to avoid calling it from
* the main thread of an application.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param startMessageId first message identifier as specified in TS 23.041 (3GPP)
* or C.R1001-G (3GPP2)
* @param endMessageId last message identifier as specified in TS 23.041 (3GPP)
@@ -1286,8 +1848,9 @@
try {
ISms iSms = getISmsService();
if (iSms != null) {
- // If getSubIdOrDefault() returns INVALID, we will use the default phone internally.
- success = iSms.disableCellBroadcastRangeForSubscriber(getSubIdOrDefault(),
+ // If getSubscriptionId() returns INVALID or an inactive subscription, we will use
+ // the default phone internally.
+ success = iSms.disableCellBroadcastRangeForSubscriber(getSubscriptionId(),
startMessageId, endMessageId, ranType);
}
} catch (RemoteException ex) {
@@ -1301,6 +1864,16 @@
* Create a list of <code>SmsMessage</code>s from a list of RawSmsData
* records returned by <code>getAllMessagesFromIcc()</code>
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param records SMS EF records, returned by
* <code>getAllMessagesFromIcc</code>
* @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
@@ -1328,6 +1901,16 @@
* SMS over IMS is supported if IMS is registered and SMS is supported
* on IMS.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @return true if SMS over IMS is supported, false otherwise
*
* @see #getImsSmsFormat()
@@ -1348,8 +1931,17 @@
}
/**
- * Gets SMS format supported on IMS. SMS over IMS format is
- * either 3GPP or 3GPP2.
+ * Gets SMS format supported on IMS. SMS over IMS format is either 3GPP or 3GPP2.
+ *
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
*
* @return SmsMessage.FORMAT_3GPP,
* SmsMessage.FORMAT_3GPP2
@@ -1375,15 +1967,12 @@
/**
* Get default sms subscription id
*
- * @return the default SMS subscription id
+ * @return the user-defined default SMS subscription id or
+ * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if no default is set.
*/
public static int getDefaultSmsSubscriptionId() {
- ISms iSms = null;
try {
- iSms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
- return iSms.getPreferredSmsSubscription();
- } catch (RemoteException ex) {
- return -1;
+ return SubscriptionManager.getDefaultSmsSubscriptionId();
} catch (NullPointerException ex) {
return -1;
}
@@ -1556,6 +2145,15 @@
/**
* Send an MMS message
*
+ * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param context application context
* @param contentUri the content Uri from which the message pdu will be read
* @param locationUrl the optional location url where message should be sent to
@@ -1586,6 +2184,15 @@
/**
* Download an MMS message from carrier by a given location URL
*
+ * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param context application context
* @param locationUrl the location URL of the MMS message to be downloaded, usually obtained
* from the MMS WAP push notification
@@ -1609,9 +2216,8 @@
if (iMms == null) {
return;
}
- iMms.downloadMessage(
- getSubscriptionId(), ActivityThread.currentPackageName(), locationUrl,
- contentUri, configOverrides, downloadedIntent);
+ iMms.downloadMessage(getSubscriptionId(), ActivityThread.currentPackageName(),
+ locationUrl, contentUri, configOverrides, downloadedIntent);
} catch (RemoteException e) {
// Ignore it
}
@@ -1849,6 +2455,15 @@
*
* You can only send a failed text message or a draft text message.
*
+ * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+ * manager on a multi-SIM device, this operation may fail sending the SMS message because no
+ * suitable default subscription could be found. In this case, if {@code sentIntent} is
+ * non-null, then the {@link PendingIntent} will be sent with an error code
+ * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
+ * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
+ * where this operation may fail.
+ * </p>
+ *
* @param messageUri the URI of the stored message
* @param scAddress is the service center address or null to use the current default SMSC
* @param sentIntent if not NULL this <code>PendingIntent</code> is
@@ -1876,14 +2491,25 @@
if (messageUri == null) {
throw new IllegalArgumentException("Empty message URI");
}
- try {
- ISms iSms = getISmsServiceOrThrow();
- iSms.sendStoredText(
- getSubscriptionId(), ActivityThread.currentPackageName(), messageUri,
- scAddress, sentIntent, deliveryIntent);
- } catch (RemoteException ex) {
- // ignore it
- }
+ final Context context = ActivityThread.currentApplication().getApplicationContext();
+ resolveSubscriptionForOperation(new SubscriptionResolverResult() {
+ @Override
+ public void onSuccess(int subId) {
+ try {
+ ISms iSms = getISmsServiceOrThrow();
+ iSms.sendStoredText(subId, ActivityThread.currentPackageName(), messageUri,
+ scAddress, sentIntent, deliveryIntent);
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendStoredTextMessage: Couldn't send SMS - Exception: "
+ + e.getMessage());
+ notifySmsGenericError(sentIntent);
+ }
+ }
+ @Override
+ public void onFailure() {
+ notifySmsErrorNoDefaultSet(context, sentIntent);
+ }
+ });
}
/**
@@ -1893,6 +2519,15 @@
* The provided <code>PendingIntent</code> lists should match the part number of the
* divided text of the stored message by using <code>divideMessage</code>
*
+ * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+ * manager on a multi-SIM device, this operation may fail sending the SMS message because no
+ * suitable default subscription could be found. In this case, if {@code sentIntent} is
+ * non-null, then the {@link PendingIntent} will be sent with an error code
+ * {@code RESULT_ERROR_GENERIC_FAILURE} and an extra string {@code "noDefault"} containing the
+ * boolean value {@code true}. See {@link #getDefault()} for more information on the conditions
+ * where this operation may fail.
+ * </p>
+ *
* @param messageUri the URI of the stored message
* @param scAddress is the service center address or null to use
* the current default SMSC
@@ -1924,14 +2559,25 @@
if (messageUri == null) {
throw new IllegalArgumentException("Empty message URI");
}
- try {
- ISms iSms = getISmsServiceOrThrow();
- iSms.sendStoredMultipartText(
- getSubscriptionId(), ActivityThread.currentPackageName(), messageUri,
- scAddress, sentIntents, deliveryIntents);
- } catch (RemoteException ex) {
- // ignore it
- }
+ final Context context = ActivityThread.currentApplication().getApplicationContext();
+ resolveSubscriptionForOperation(new SubscriptionResolverResult() {
+ @Override
+ public void onSuccess(int subId) {
+ try {
+ ISms iSms = getISmsServiceOrThrow();
+ iSms.sendStoredMultipartText(subId, ActivityThread.currentPackageName(),
+ messageUri, scAddress, sentIntents, deliveryIntents);
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendStoredTextMessage: Couldn't send SMS - Exception: "
+ + e.getMessage());
+ notifySmsGenericError(sentIntents);
+ }
+ }
+ @Override
+ public void onFailure() {
+ notifySmsErrorNoDefaultSet(context, sentIntents);
+ }
+ });
}
/**
@@ -1940,6 +2586,15 @@
* This is used for sending a previously sent, but failed-to-send, message or
* for sending a text message that has been stored as a draft.
*
+ * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param messageUri the URI of the stored message
* @param configOverrides the carrier-specific messaging configuration values to override for
* sending the message.
@@ -2013,6 +2668,16 @@
/**
* Get carrier-dependent configuration values.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @return bundle key/values pairs of configuration values
*/
public Bundle getCarrierConfigValues() {
@@ -2028,7 +2693,7 @@
}
/**
- * Create a single use app specific incoming SMS request for the the calling package.
+ * Create a single use app specific incoming SMS request for the calling package.
*
* This method returns a token that if included in a subsequent incoming SMS message will cause
* {@code intent} to be sent with the SMS data.
@@ -2039,6 +2704,15 @@
* An app can only have one request at a time, if the app already has a request pending it will
* be replaced with a new request.
*
+ * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @return Token to include in an SMS message. The token will be 11 characters long.
* @see android.provider.Telephony.Sms.Intents#getMessagesFromIntent
*/
@@ -2068,6 +2742,15 @@
* Get SMS messages for the calling financial app.
* The result will be delivered asynchronously in the passing in callback interface.
*
+ * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param params the parameters to filter SMS messages returned.
* @param executor the executor on which callback will be invoked.
* @param callback a callback to receive CursorWindow with SMS messages.
@@ -2144,6 +2827,15 @@
* An app can only have one request at a time, if the app already has a request pending it will
* be replaced with a new request.
*
+ * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param prefixes this is a list of prefixes string separated by REGEX_PREFIX_DELIMITER. The
* matching SMS message should have at least one of the prefixes in the beginning of the
* message.
@@ -2156,7 +2848,7 @@
try {
ISms iccSms = getISmsServiceOrThrow();
return iccSms.createAppSpecificSmsTokenWithPackageInfo(getSubscriptionId(),
- ActivityThread.currentPackageName(), prefixes, intent);
+ ActivityThread.currentPackageName(), prefixes, intent);
} catch (RemoteException ex) {
ex.rethrowFromSystemServer();
@@ -2285,6 +2977,16 @@
* NOTE: the caller is expected to strip non-digits from the destination number with
* {@link PhoneNumberUtils#extractNetworkPortion} before calling this method.
*
+ * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
+ * applications or the Telephony framework and will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this message will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
+ * operation is performed on the correct subscription.
+ * </p>
+ *
* @param destAddress the destination address to test for possible short code
* @param countryIso the ISO country code
*
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index c57f9e6..f31ac2e 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -173,6 +173,11 @@
private ParcelUuid mGroupUUID;
/**
+ * A package name that specifies who created the group. Null if mGroupUUID is null.
+ */
+ private String mGroupOwner;
+
+ /**
* Whether group of the subscription is disabled.
* This is only useful if it's a grouped opportunistic subscription. In this case, if all
* primary (non-opportunistic) subscriptions in the group are deactivated (unplugged pSIM
@@ -203,9 +208,10 @@
Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
@Nullable UiccAccessRule[] accessRules, String cardString) {
this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
- roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString,
- false, null, TelephonyManager.UNKNOWN_CARRIER_ID,
- SubscriptionManager.PROFILE_CLASS_DEFAULT);
+ roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString, -1,
+ false, null, false, TelephonyManager.UNKNOWN_CARRIER_ID,
+ SubscriptionManager.PROFILE_CLASS_DEFAULT,
+ SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null);
}
/**
@@ -219,7 +225,7 @@
this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString, -1,
isOpportunistic, groupUUID, false, carrierId, profileClass,
- SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
+ SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null);
}
/**
@@ -229,8 +235,8 @@
CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
@Nullable UiccAccessRule[] accessRules, String cardString, int cardId,
- boolean isOpportunistic, @Nullable String groupUUID,
- boolean isGroupDisabled, int carrierId, int profileClass, int subType) {
+ boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled,
+ int carrierId, int profileClass, int subType, @Nullable String groupOwner) {
this.mId = id;
this.mIccId = iccId;
this.mSimSlotIndex = simSlotIndex;
@@ -254,6 +260,7 @@
this.mCarrierId = carrierId;
this.mProfileClass = profileClass;
this.mSubscriptionType = subType;
+ this.mGroupOwner = groupOwner;
}
/**
@@ -500,6 +507,15 @@
}
/**
+ * Return owner package of group the subscription belongs to.
+ *
+ * @hide
+ */
+ public @Nullable String getGroupOwner() {
+ return mGroupOwner;
+ }
+
+ /**
* @return the profile class of this subscription.
* @hide
*/
@@ -646,11 +662,12 @@
int subType = source.readInt();
String[] ehplmns = source.readStringArray();
String[] hplmns = source.readStringArray();
+ String groupOwner = source.readString();
SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName,
carrierName, nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc,
countryIso, isEmbedded, accessRules, cardString, cardId, isOpportunistic,
- groupUUID, isGroupDisabled, carrierid, profileClass, subType);
+ groupUUID, isGroupDisabled, carrierid, profileClass, subType, groupOwner);
info.setAssociatedPlmns(ehplmns, hplmns);
return info;
}
@@ -688,6 +705,7 @@
dest.writeInt(mSubscriptionType);
dest.writeStringArray(mEhplmns);
dest.writeStringArray(mHplmns);
+ dest.writeString(mGroupOwner);
}
@Override
@@ -727,7 +745,8 @@
+ " profileClass=" + mProfileClass
+ " ehplmns = " + Arrays.toString(mEhplmns)
+ " hplmns = " + Arrays.toString(mHplmns)
- + " subscriptionType=" + mSubscriptionType + "}";
+ + " subscriptionType=" + mSubscriptionType
+ + " mGroupOwner=" + mGroupOwner + "}";
}
@Override
@@ -735,7 +754,7 @@
return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc,
mCountryIso, mCardString, mCardId, mDisplayName, mCarrierName, mAccessRules,
- mIsGroupDisabled, mCarrierId, mProfileClass);
+ mIsGroupDisabled, mCarrierId, mProfileClass, mGroupOwner);
}
@Override
@@ -767,6 +786,7 @@
&& Objects.equals(mCountryIso, toCompare.mCountryIso)
&& Objects.equals(mCardString, toCompare.mCardString)
&& Objects.equals(mCardId, toCompare.mCardId)
+ && Objects.equals(mGroupOwner, toCompare.mGroupOwner)
&& TextUtils.equals(mDisplayName, toCompare.mDisplayName)
&& TextUtils.equals(mCarrierName, toCompare.mCarrierName)
&& Arrays.equals(mAccessRules, toCompare.mAccessRules)
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 32105ad..b5da2ee 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -686,6 +686,15 @@
* @hide
*/
public static final String GROUP_UUID = "group_uuid";
+
+ /**
+ * TelephonyProvider column name for group owner. It's the package name who created
+ * the subscription group.
+ *
+ * @hide
+ */
+ public static final String GROUP_OWNER = "group_owner";
+
/**
* TelephonyProvider column name for whether a subscription is metered or not, that is, whether
* the network it connects to charges for subscription or not. For example, paid CBRS or unpaid.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 903e533..dab1e6f 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3836,10 +3836,12 @@
}
/**
- * Return the set of subscriber IDs that should be considered as "merged
- * together" for data usage purposes. This is commonly {@code null} to
- * indicate no merging is required. Any returned subscribers are sorted in a
- * deterministic order.
+ * Return the set of subscriber IDs that should be considered "merged together" for data usage
+ * purposes. This is commonly {@code null} to indicate no merging is required. Any returned
+ * subscribers are sorted in a deterministic order.
+ * <p>
+ * The returned set of subscriber IDs will include the subscriber ID corresponding to this
+ * TelephonyManager's subId.
*
* @hide
*/
@@ -3848,7 +3850,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.getMergedSubscriberIds(getOpPackageName());
+ return telephony.getMergedSubscriberIds(getSubId(), getOpPackageName());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4897,24 +4899,20 @@
boolean notifyNow = (getITelephony() != null);
ITelephonyRegistry registry = getTelephonyRegistry();
if (registry != null) {
- int subId;
- // subId from phonestatelistner is deprecated Q on forward, use the subId from
- // TelephonyManager instance.
- if (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.Q
- || listener.mSubId == null) {
- subId = mSubId;
- } else {
+ // subId from PhoneStateListener is deprecated Q on forward, use the subId from
+ // TelephonyManager instance. keep using subId from PhoneStateListener for pre-Q.
+ int subId = mSubId;
+ if (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.Q) {
+ // since mSubId in PhoneStateListener is deprecated from Q on forward, this is
+ // the only place to set mSubId and its for "informational" only.
+ // TODO: remove this once we completely get rid of mSubId in PhoneStateListener
+ listener.mSubId = (events == PhoneStateListener.LISTEN_NONE)
+ ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : subId;
+ } else if (listener.mSubId != null) {
subId = listener.mSubId;
}
-
registry.listenForSubscriber(subId, getOpPackageName(),
listener.callback, events, notifyNow);
- // TODO: remove this once we remove PhoneStateListener constructor with subId.
- if (events == PhoneStateListener.LISTEN_NONE) {
- listener.mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- } else {
- listener.mSubId = subId;
- }
} else {
Rlog.w(TAG, "telephony registry not ready.");
}
@@ -7477,7 +7475,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.checkCarrierPrivilegesForPackage(pkgName);
+ return telephony.checkCarrierPrivilegesForPackage(getSubId(), pkgName);
} catch (RemoteException ex) {
Rlog.e(TAG, "checkCarrierPrivilegesForPackage RemoteException", ex);
} catch (NullPointerException ex) {
@@ -7528,7 +7526,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getPackagesWithCarrierPrivileges();
+ return telephony.getPackagesWithCarrierPrivileges(getPhoneId());
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getPackagesWithCarrierPrivileges RemoteException", ex);
@@ -7539,6 +7537,22 @@
}
/** @hide */
+ public List<String> getPackagesWithCarrierPrivilegesForAllPhones() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getPackagesWithCarrierPrivilegesForAllPhones();
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getPackagesWithCarrierPrivilegesForAllPhones RemoteException", ex);
+ } catch (NullPointerException ex) {
+ Rlog.e(TAG, "getPackagesWithCarrierPrivilegesForAllPhones NPE", ex);
+ }
+ return Collections.EMPTY_LIST;
+ }
+
+
+ /** @hide */
@SystemApi
@SuppressLint("Doclava125")
public void dial(String number) {
diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index 9a8d7cd..785d7ae 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -140,10 +140,6 @@
return mIsEuicc;
}
- /**
- * Returns the ICCID of a the UICC in the given slot, or the EID if it is an eUICC. Note that if
- * the value is unavailble this will return null.
- */
public String getCardId() {
return mCardId;
}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index a86fda4..a78bae4 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1273,6 +1273,23 @@
}
/**
+ * Get supported APN types
+ *
+ * @return list of APN types
+ * @hide
+ */
+ @ApnType
+ public List<Integer> getApnTypes() {
+ List<Integer> types = new ArrayList<>();
+ for (Integer type : APN_TYPE_INT_MAP.keySet()) {
+ if ((mApnTypeBitmask & type) == type) {
+ types.add(type);
+ }
+ }
+ return types;
+ }
+
+ /**
* @param apnTypeBitmask bitmask of APN types.
* @return comma delimited list of APN types.
* @hide
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index 22f078f..7b51457 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -558,6 +558,24 @@
} else if (this.getDisplayPriorityScore()
< emergencyNumber.getDisplayPriorityScore()) {
return 1;
+ } else if (this.getNumber().compareTo(emergencyNumber.getNumber()) != 0) {
+ return this.getNumber().compareTo(emergencyNumber.getNumber());
+ } else if (this.getCountryIso().compareTo(emergencyNumber.getCountryIso()) != 0) {
+ return this.getCountryIso().compareTo(emergencyNumber.getCountryIso());
+ } else if (this.getMnc().compareTo(emergencyNumber.getMnc()) != 0) {
+ return this.getMnc().compareTo(emergencyNumber.getMnc());
+ } else if (this.getEmergencyServiceCategoryBitmask()
+ != emergencyNumber.getEmergencyServiceCategoryBitmask()) {
+ return this.getEmergencyServiceCategoryBitmask()
+ > emergencyNumber.getEmergencyServiceCategoryBitmask() ? -1 : 1;
+ } else if (this.getEmergencyUrns().toString().compareTo(
+ emergencyNumber.getEmergencyUrns().toString()) != 0) {
+ return this.getEmergencyUrns().toString().compareTo(
+ emergencyNumber.getEmergencyUrns().toString());
+ } else if (this.getEmergencyCallRouting()
+ != emergencyNumber.getEmergencyCallRouting()) {
+ return this.getEmergencyCallRouting()
+ > emergencyNumber.getEmergencyCallRouting() ? -1 : 1;
} else {
return 0;
}
@@ -579,13 +597,9 @@
if (emergencyNumberList == null) {
return;
}
- Set<EmergencyNumber> mergedEmergencyNumber = new HashSet<>();
+ Set<Integer> duplicatedEmergencyNumberPosition = new HashSet<>();
for (int i = 0; i < emergencyNumberList.size(); i++) {
- // Skip the check because it was merged.
- if (mergedEmergencyNumber.contains(emergencyNumberList.get(i))) {
- continue;
- }
- for (int j = i + 1; j < emergencyNumberList.size(); j++) {
+ for (int j = 0; j < i; j++) {
if (areSameEmergencyNumbers(
emergencyNumberList.get(i), emergencyNumberList.get(j))) {
Rlog.e(LOG_TAG, "Found unexpected duplicate numbers: "
@@ -594,14 +608,15 @@
emergencyNumberList.set(i, mergeSameEmergencyNumbers(
emergencyNumberList.get(i), emergencyNumberList.get(j)));
// Mark the emergency number has been merged
- mergedEmergencyNumber.add(emergencyNumberList.get(j));
+ duplicatedEmergencyNumberPosition.add(j);
}
}
}
- // Remove the marked emergency number in the orignal list
- for (int i = 0; i < emergencyNumberList.size(); i++) {
- if (mergedEmergencyNumber.contains(emergencyNumberList.get(i))) {
- emergencyNumberList.remove(i--);
+
+ // Remove the marked emergency number in the original list
+ for (int i = emergencyNumberList.size() - 1; i >= 0; i--) {
+ if (duplicatedEmergencyNumberPosition.contains(i)) {
+ emergencyNumberList.remove(i);
}
}
Collections.sort(emergencyNumberList);
diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
index 464db34..32b4382 100644
--- a/telephony/java/android/telephony/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -457,7 +457,7 @@
}
public boolean isTypeInterrogation() {
- return (getServiceType() == SS_INTERROGATION);
+ return (getRequestType() == SS_INTERROGATION);
}
/**
diff --git a/telephony/java/android/telephony/ims/Rcs1To1Thread.java b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
index 0bb1b43..e90548a 100644
--- a/telephony/java/android/telephony/ims/Rcs1To1Thread.java
+++ b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
@@ -33,8 +33,8 @@
*
* @hide
*/
- public Rcs1To1Thread(int threadId) {
- super(threadId);
+ public Rcs1To1Thread(RcsControllerCall rcsControllerCall, int threadId) {
+ super(rcsControllerCall, threadId);
mThreadId = threadId;
}
@@ -56,7 +56,9 @@
*/
@WorkerThread
public long getFallbackThreadId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.get1To1ThreadFallbackThreadId(mThreadId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.get1To1ThreadFallbackThreadId(mThreadId,
+ callingPackage));
}
/**
@@ -69,8 +71,9 @@
*/
@WorkerThread
public void setFallbackThreadId(long fallbackThreadId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.set1To1ThreadFallbackThreadId(mThreadId, fallbackThreadId));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.set1To1ThreadFallbackThreadId(mThreadId,
+ fallbackThreadId, callingPackage));
}
/**
@@ -81,6 +84,9 @@
@WorkerThread
public RcsParticipant getRecipient() throws RcsMessageStoreException {
return new RcsParticipant(
- RcsControllerCall.call(iRcs -> iRcs.get1To1ThreadOtherParticipantId(mThreadId)));
+ mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.get1To1ThreadOtherParticipantId(mThreadId,
+ callingPackage)));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsControllerCall.java b/telephony/java/android/telephony/ims/RcsControllerCall.java
index 5512c4c..a2d68ad 100644
--- a/telephony/java/android/telephony/ims/RcsControllerCall.java
+++ b/telephony/java/android/telephony/ims/RcsControllerCall.java
@@ -27,38 +27,38 @@
* @hide - not meant for public use
*/
class RcsControllerCall {
- static <R> R call(RcsServiceCall<R> serviceCall) throws RcsMessageStoreException {
+ private final Context mContext;
+
+ RcsControllerCall(Context context) {
+ mContext = context;
+ }
+
+ <R> R call(RcsServiceCall<R> serviceCall) throws RcsMessageStoreException {
IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_RCS_SERVICE));
if (iRcs == null) {
throw new RcsMessageStoreException("Could not connect to RCS storage service");
}
try {
- return serviceCall.methodOnIRcs(iRcs);
+ return serviceCall.methodOnIRcs(iRcs, mContext.getOpPackageName());
} catch (RemoteException exception) {
throw new RcsMessageStoreException(exception.getMessage());
}
}
- static void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall)
+ void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall)
throws RcsMessageStoreException {
- IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_RCS_SERVICE));
- if (iRcs == null) {
- throw new RcsMessageStoreException("Could not connect to RCS storage service");
- }
-
- try {
- serviceCall.methodOnIRcs(iRcs);
- } catch (RemoteException exception) {
- throw new RcsMessageStoreException(exception.getMessage());
- }
+ call((iRcs, callingPackage) -> {
+ serviceCall.methodOnIRcs(iRcs, callingPackage);
+ return null;
+ });
}
interface RcsServiceCall<R> {
- R methodOnIRcs(IRcs iRcs) throws RemoteException;
+ R methodOnIRcs(IRcs iRcs, String callingPackage) throws RemoteException;
}
interface RcsServiceCallWithNoReturn {
- void methodOnIRcs(IRcs iRcs) throws RemoteException;
+ void methodOnIRcs(IRcs iRcs, String callingPackage) throws RemoteException;
}
}
diff --git a/telephony/java/android/telephony/ims/RcsEvent.java b/telephony/java/android/telephony/ims/RcsEvent.java
index 994b27a..9dd0720 100644
--- a/telephony/java/android/telephony/ims/RcsEvent.java
+++ b/telephony/java/android/telephony/ims/RcsEvent.java
@@ -40,5 +40,5 @@
*
* @hide
*/
- abstract void persist() throws RcsMessageStoreException;
+ abstract void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException;
}
diff --git a/telephony/java/android/telephony/ims/RcsEventDescriptor.java b/telephony/java/android/telephony/ims/RcsEventDescriptor.java
index 8e3f6cd..b44adea 100644
--- a/telephony/java/android/telephony/ims/RcsEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsEventDescriptor.java
@@ -38,7 +38,7 @@
* descriptor.
*/
@VisibleForTesting(visibility = PROTECTED)
- public abstract RcsEvent createRcsEvent();
+ public abstract RcsEvent createRcsEvent(RcsControllerCall rcsControllerCall);
RcsEventDescriptor(Parcel in) {
mTimestamp = in.readLong();
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
index e30745b7..b972d55 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
@@ -39,9 +39,9 @@
mEvents = events;
}
- protected RcsEventQueryResult getRcsEventQueryResult() {
+ protected RcsEventQueryResult getRcsEventQueryResult(RcsControllerCall rcsControllerCall) {
List<RcsEvent> rcsEvents = mEvents.stream()
- .map(RcsEventDescriptor::createRcsEvent)
+ .map(rcsEvent -> rcsEvent.createRcsEvent(rcsControllerCall))
.collect(Collectors.toList());
return new RcsEventQueryResult(mContinuationToken, rcsEvents);
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferPart.java b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
index 3816cd4..ef66a76 100644
--- a/telephony/java/android/telephony/ims/RcsFileTransferPart.java
+++ b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
@@ -103,12 +103,15 @@
public @interface RcsFileTransferStatus {
}
+ private final RcsControllerCall mRcsControllerCall;
+
private int mId;
/**
* @hide
*/
- RcsFileTransferPart(int id) {
+ RcsFileTransferPart(RcsControllerCall rcsControllerCall, int id) {
+ mRcsControllerCall = rcsControllerCall;
mId = id;
}
@@ -134,7 +137,9 @@
*/
@WorkerThread
public void setFileTransferSessionId(String sessionId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferSessionId(mId, sessionId));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferSessionId(mId, sessionId,
+ callingPackage));
}
/**
@@ -143,7 +148,8 @@
*/
@WorkerThread
public String getFileTransferSessionId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferSessionId(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferSessionId(mId, callingPackage));
}
/**
@@ -155,7 +161,9 @@
*/
@WorkerThread
public void setContentUri(Uri contentUri) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferContentUri(mId, contentUri));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferContentUri(mId, contentUri,
+ callingPackage));
}
/**
@@ -165,7 +173,8 @@
@Nullable
@WorkerThread
public Uri getContentUri() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferContentUri(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferContentUri(mId, callingPackage));
}
/**
@@ -177,8 +186,9 @@
*/
@WorkerThread
public void setContentMimeType(String contentMimeType) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setFileTransferContentType(mId, contentMimeType));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferContentType(mId, contentMimeType,
+ callingPackage));
}
/**
@@ -188,7 +198,8 @@
@WorkerThread
@Nullable
public String getContentMimeType() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferContentType(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferContentType(mId, callingPackage));
}
/**
@@ -199,8 +210,9 @@
*/
@WorkerThread
public void setFileSize(long contentLength) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setFileTransferFileSize(mId, contentLength));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferFileSize(mId, contentLength,
+ callingPackage));
}
/**
@@ -209,7 +221,8 @@
*/
@WorkerThread
public long getFileSize() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferFileSize(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferFileSize(mId, callingPackage));
}
/**
@@ -222,8 +235,9 @@
*/
@WorkerThread
public void setTransferOffset(long transferOffset) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setFileTransferTransferOffset(mId, transferOffset));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferTransferOffset(mId, transferOffset,
+ callingPackage));
}
/**
@@ -232,7 +246,8 @@
*/
@WorkerThread
public long getTransferOffset() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferTransferOffset(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferTransferOffset(mId, callingPackage));
}
/**
@@ -244,7 +259,8 @@
@WorkerThread
public void setFileTransferStatus(@RcsFileTransferStatus int status)
throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferStatus(mId, status));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferStatus(mId, status, callingPackage));
}
/**
@@ -253,7 +269,8 @@
*/
@WorkerThread
public @RcsFileTransferStatus int getFileTransferStatus() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferStatus(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferStatus(mId, callingPackage));
}
/**
@@ -262,7 +279,8 @@
*/
@WorkerThread
public int getWidth() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferWidth(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferWidth(mId, callingPackage));
}
/**
@@ -273,7 +291,8 @@
*/
@WorkerThread
public void setWidth(int width) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferWidth(mId, width));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferWidth(mId, width, callingPackage));
}
/**
@@ -282,7 +301,8 @@
*/
@WorkerThread
public int getHeight() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferHeight(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferHeight(mId, callingPackage));
}
/**
@@ -293,7 +313,8 @@
*/
@WorkerThread
public void setHeight(int height) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferHeight(mId, height));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferHeight(mId, height, callingPackage));
}
/**
@@ -302,7 +323,8 @@
*/
@WorkerThread
public long getLength() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferLength(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferLength(mId, callingPackage));
}
/**
@@ -313,7 +335,8 @@
*/
@WorkerThread
public void setLength(long length) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferLength(mId, length));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferLength(mId, length, callingPackage));
}
/**
@@ -323,7 +346,8 @@
*/
@WorkerThread
public Uri getPreviewUri() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewUri(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferPreviewUri(mId, callingPackage));
}
/**
@@ -334,7 +358,9 @@
*/
@WorkerThread
public void setPreviewUri(Uri previewUri) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferPreviewUri(mId, previewUri));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferPreviewUri(mId, previewUri,
+ callingPackage));
}
/**
@@ -343,7 +369,8 @@
*/
@WorkerThread
public String getPreviewMimeType() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewType(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferPreviewType(mId, callingPackage));
}
/**
@@ -354,7 +381,8 @@
*/
@WorkerThread
public void setPreviewMimeType(String previewMimeType) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setFileTransferPreviewType(mId, previewMimeType));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferPreviewType(mId, previewMimeType,
+ callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThread.java b/telephony/java/android/telephony/ims/RcsGroupThread.java
index 8cd633b..30abcb4 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThread.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThread.java
@@ -38,8 +38,8 @@
*
* @hide
*/
- public RcsGroupThread(int threadId) {
- super(threadId);
+ public RcsGroupThread(RcsControllerCall rcsControllerCall, int threadId) {
+ super(rcsControllerCall, threadId);
}
/**
@@ -58,7 +58,8 @@
@Nullable
@WorkerThread
public String getGroupName() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadName(mThreadId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getGroupThreadName(mThreadId, callingPackage));
}
/**
@@ -69,7 +70,9 @@
*/
@WorkerThread
public void setGroupName(String groupName) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadName(mThreadId, groupName));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setGroupThreadName(mThreadId, groupName,
+ callingPackage));
}
/**
@@ -79,7 +82,8 @@
*/
@Nullable
public Uri getGroupIcon() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadIcon(mThreadId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getGroupThreadIcon(mThreadId, callingPackage));
}
/**
@@ -90,7 +94,9 @@
*/
@WorkerThread
public void setGroupIcon(@Nullable Uri groupIcon) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadIcon(mThreadId, groupIcon));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setGroupThreadIcon(mThreadId, groupIcon,
+ callingPackage));
}
/**
@@ -100,8 +106,11 @@
@Nullable
@WorkerThread
public RcsParticipant getOwner() throws RcsMessageStoreException {
- return new RcsParticipant(RcsControllerCall.call(
- iRcs -> iRcs.getGroupThreadOwner(mThreadId)));
+ return new RcsParticipant(
+ mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getGroupThreadOwner(mThreadId,
+ callingPackage)));
}
/**
@@ -114,8 +123,9 @@
*/
@WorkerThread
public void setOwner(@Nullable RcsParticipant participant) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setGroupThreadOwner(mThreadId, participant.getId()));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setGroupThreadOwner(mThreadId, participant.getId(),
+ callingPackage));
}
/**
@@ -133,8 +143,9 @@
return;
}
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.addParticipantToGroupThread(mThreadId, participant.getId()));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.addParticipantToGroupThread(mThreadId,
+ participant.getId(), callingPackage));
}
/**
@@ -150,8 +161,9 @@
return;
}
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.removeParticipantFromGroupThread(mThreadId, participant.getId()));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.removeParticipantFromGroupThread(mThreadId,
+ participant.getId(), callingPackage));
}
/**
@@ -169,8 +181,11 @@
RcsParticipantQueryParams queryParameters =
new RcsParticipantQueryParams.Builder().setThread(this).build();
- RcsParticipantQueryResult queryResult = RcsControllerCall.call(
- iRcs -> iRcs.getParticipants(queryParameters));
+ RcsParticipantQueryResult queryResult = new RcsParticipantQueryResult(
+ mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getParticipants(queryParameters,
+ callingPackage)));
List<RcsParticipant> participantList = queryResult.getParticipants();
Set<RcsParticipant> participantSet = new LinkedHashSet<>(participantList);
@@ -186,7 +201,9 @@
@Nullable
@WorkerThread
public Uri getConferenceUri() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadConferenceUri(mThreadId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getGroupThreadConferenceUri(mThreadId,
+ callingPackage));
}
/**
@@ -199,7 +216,8 @@
@Nullable
@WorkerThread
public void setConferenceUri(Uri conferenceUri) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setGroupThreadConferenceUri(mThreadId, conferenceUri));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setGroupThreadConferenceUri(mThreadId, conferenceUri,
+ callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
index 4a6b963..f4beef7f 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
@@ -23,14 +23,14 @@
* @hide
*/
public abstract class RcsGroupThreadEvent extends RcsEvent {
- private final int mRcsGroupThreadId;
- private final int mOriginatingParticipantId;
+ private final RcsGroupThread mRcsGroupThread;
+ private final RcsParticipant mOriginatingParticipant;
- RcsGroupThreadEvent(long timestamp, int rcsGroupThreadId,
- int originatingParticipantId) {
+ RcsGroupThreadEvent(long timestamp, RcsGroupThread rcsGroupThread,
+ RcsParticipant originatingParticipant) {
super(timestamp);
- mRcsGroupThreadId = rcsGroupThreadId;
- mOriginatingParticipantId = originatingParticipantId;
+ mRcsGroupThread = rcsGroupThread;
+ mOriginatingParticipant = originatingParticipant;
}
/**
@@ -38,7 +38,7 @@
*/
@NonNull
public RcsGroupThread getRcsGroupThread() {
- return new RcsGroupThread(mRcsGroupThreadId);
+ return mRcsGroupThread;
}
/**
@@ -46,6 +46,6 @@
*/
@NonNull
public RcsParticipant getOriginatingParticipant() {
- return new RcsParticipant(mOriginatingParticipantId);
+ return mOriginatingParticipant;
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
index 3c6c74f..23e39ff 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
@@ -40,9 +40,10 @@
* @param newIcon {@link Uri} to the new icon of this {@link RcsGroupThread}
* @see RcsMessageStore#persistRcsEvent(RcsEvent)
*/
- public RcsGroupThreadIconChangedEvent(long timestamp, @NonNull RcsGroupThread rcsGroupThread,
- @NonNull RcsParticipant originatingParticipant, @Nullable Uri newIcon) {
- super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+ public RcsGroupThreadIconChangedEvent(long timestamp,
+ @NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
+ @Nullable Uri newIcon) {
+ super(timestamp, rcsGroupThread, originatingParticipant);
mNewIcon = newIcon;
}
@@ -61,10 +62,10 @@
* @hide - not meant for public use.
*/
@Override
- public void persist() throws RcsMessageStoreException {
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
// TODO ensure failure throws
- RcsControllerCall.call(iRcs -> iRcs.createGroupThreadIconChangedEvent(
+ rcsControllerCall.call((iRcs, callingPackage) -> iRcs.createGroupThreadIconChangedEvent(
getTimestamp(), getRcsGroupThread().getThreadId(),
- getOriginatingParticipant().getId(), mNewIcon));
+ getOriginatingParticipant().getId(), mNewIcon, callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
index bcadc80..9350e40 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
@@ -38,9 +38,10 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadIconChangedEvent createRcsEvent() {
- return new RcsGroupThreadIconChangedEvent(mTimestamp, new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId), mNewIcon);
+ public RcsGroupThreadIconChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
+ return new RcsGroupThreadIconChangedEvent(mTimestamp,
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId), mNewIcon);
}
public static final @NonNull Creator<RcsGroupThreadIconChangedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
index 5403253..a6a0867 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
@@ -41,7 +41,7 @@
*/
public RcsGroupThreadNameChangedEvent(long timestamp, @NonNull RcsGroupThread rcsGroupThread,
@NonNull RcsParticipant originatingParticipant, @Nullable String newName) {
- super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+ super(timestamp, rcsGroupThread, originatingParticipant);
mNewName = newName;
}
@@ -60,9 +60,9 @@
* @hide - not meant for public use.
*/
@Override
- public void persist() throws RcsMessageStoreException {
- RcsControllerCall.call(iRcs -> iRcs.createGroupThreadNameChangedEvent(
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+ rcsControllerCall.call((iRcs, callingPackage) -> iRcs.createGroupThreadNameChangedEvent(
getTimestamp(), getRcsGroupThread().getThreadId(),
- getOriginatingParticipant().getId(), mNewName));
+ getOriginatingParticipant().getId(), mNewName, callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
index 597fa0a..f9ccdd5 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
@@ -37,11 +37,11 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadNameChangedEvent createRcsEvent() {
+ public RcsGroupThreadNameChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
return new RcsGroupThreadNameChangedEvent(
mTimestamp,
- new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId),
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
mNewName);
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
index 48be479..694c7de 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
@@ -30,19 +30,20 @@
* Creates a new {@link RcsGroupThreadParticipantJoinedEvent}. This event is not persisted into
* storage until {@link RcsMessageStore#persistRcsEvent(RcsEvent)} is called.
*
- * @param timestamp The timestamp of when this event happened, in milliseconds passed after
- * midnight, January 1st, 1970 UTC
- * @param rcsGroupThread The {@link RcsGroupThread} that this event happened on
+ * @param timestamp The timestamp of when this event happened, in milliseconds
+ * passed after
+ * midnight, January 1st, 1970 UTC
+ * @param rcsGroupThread The {@link RcsGroupThread} that this event happened on
* @param originatingParticipant The {@link RcsParticipant} that added or invited the new
* {@link RcsParticipant} into the {@link RcsGroupThread}
- * @param joinedParticipant The new {@link RcsParticipant} that joined the
- * {@link RcsGroupThread}
+ * @param joinedParticipant The new {@link RcsParticipant} that joined the
+ * {@link RcsGroupThread}
* @see RcsMessageStore#persistRcsEvent(RcsEvent)
*/
public RcsGroupThreadParticipantJoinedEvent(long timestamp,
@NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
@NonNull RcsParticipant joinedParticipant) {
- super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+ super(timestamp, rcsGroupThread, originatingParticipant);
mJoinedParticipantId = joinedParticipant;
}
@@ -59,10 +60,11 @@
* @hide - not meant for public use.
*/
@Override
- public void persist() throws RcsMessageStoreException {
- RcsControllerCall.call(
- iRcs -> iRcs.createGroupThreadParticipantJoinedEvent(getTimestamp(),
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+ rcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.createGroupThreadParticipantJoinedEvent(
+ getTimestamp(),
getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
- getJoinedParticipant().getId()));
+ getJoinedParticipant().getId(), callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
index abea10a..4a6803e 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
@@ -36,12 +36,13 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadParticipantJoinedEvent createRcsEvent() {
+ public RcsGroupThreadParticipantJoinedEvent createRcsEvent(
+ RcsControllerCall rcsControllerCall) {
return new RcsGroupThreadParticipantJoinedEvent(
mTimestamp,
- new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId),
- new RcsParticipant(mJoinedParticipantId));
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
+ new RcsParticipant(rcsControllerCall, mJoinedParticipantId));
}
public static final @NonNull Creator<RcsGroupThreadParticipantJoinedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
index b724a3f..fec4354 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
@@ -44,7 +44,7 @@
public RcsGroupThreadParticipantLeftEvent(long timestamp,
@NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
@NonNull RcsParticipant leavingParticipant) {
- super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+ super(timestamp, rcsGroupThread, originatingParticipant);
mLeavingParticipant = leavingParticipant;
}
@@ -58,10 +58,10 @@
}
@Override
- public void persist() throws RcsMessageStoreException {
- RcsControllerCall.call(
- iRcs -> iRcs.createGroupThreadParticipantLeftEvent(getTimestamp(),
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+ rcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.createGroupThreadParticipantLeftEvent(getTimestamp(),
getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
- getLeavingParticipant().getId()));
+ getLeavingParticipant().getId(), callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
index f287db1..9b1085c 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
@@ -37,12 +37,12 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadParticipantLeftEvent createRcsEvent() {
+ public RcsGroupThreadParticipantLeftEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
return new RcsGroupThreadParticipantLeftEvent(
mTimestamp,
- new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId),
- new RcsParticipant(mLeavingParticipantId));
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
+ new RcsParticipant(rcsControllerCall, mLeavingParticipantId));
}
@NonNull
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessage.java b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
index 06e2a41..2810a49 100644
--- a/telephony/java/android/telephony/ims/RcsIncomingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
@@ -26,8 +26,8 @@
/**
* @hide
*/
- RcsIncomingMessage(int id) {
- super(id);
+ RcsIncomingMessage(RcsControllerCall rcsControllerCall, int id) {
+ super(rcsControllerCall, id);
}
/**
@@ -39,8 +39,9 @@
*/
@WorkerThread
public void setArrivalTimestamp(long arrivalTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setMessageArrivalTimestamp(mId, true, arrivalTimestamp));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setMessageArrivalTimestamp(mId, true,
+ arrivalTimestamp, callingPackage));
}
/**
@@ -50,7 +51,9 @@
*/
@WorkerThread
public long getArrivalTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageArrivalTimestamp(mId, true));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageArrivalTimestamp(mId, true,
+ callingPackage));
}
/**
@@ -62,8 +65,9 @@
*/
@WorkerThread
public void setSeenTimestamp(long notifiedTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setMessageSeenTimestamp(mId, true, notifiedTimestamp));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setMessageSeenTimestamp(mId, true, notifiedTimestamp,
+ callingPackage));
}
/**
@@ -73,7 +77,8 @@
*/
@WorkerThread
public long getSeenTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageSeenTimestamp(mId, true));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageSeenTimestamp(mId, true, callingPackage));
}
/**
@@ -83,7 +88,9 @@
@WorkerThread
public RcsParticipant getSenderParticipant() throws RcsMessageStoreException {
return new RcsParticipant(
- RcsControllerCall.call(iRcs -> iRcs.getSenderParticipant(mId)));
+ mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getSenderParticipant(mId, callingPackage)));
}
/**
diff --git a/telephony/java/android/telephony/ims/RcsManager.java b/telephony/java/android/telephony/ims/RcsManager.java
index 63dc1ac..0d6ca3c 100644
--- a/telephony/java/android/telephony/ims/RcsManager.java
+++ b/telephony/java/android/telephony/ims/RcsManager.java
@@ -25,20 +25,19 @@
*/
@SystemService(Context.TELEPHONY_RCS_SERVICE)
public class RcsManager {
+ private final RcsMessageStore mRcsMessageStore;
/**
* @hide
*/
- public RcsManager() {
- // empty constructor
+ public RcsManager(Context context) {
+ mRcsMessageStore = new RcsMessageStore(context);
}
- private static final RcsMessageStore sRcsMessageStoreInstance = new RcsMessageStore();
-
/**
* Returns an instance of {@link RcsMessageStore}
*/
public RcsMessageStore getRcsMessageStore() {
- return sRcsMessageStoreInstance;
+ return mRcsMessageStore;
}
}
diff --git a/telephony/java/android/telephony/ims/RcsMessage.java b/telephony/java/android/telephony/ims/RcsMessage.java
index b0d0d5a..4601bfd 100644
--- a/telephony/java/android/telephony/ims/RcsMessage.java
+++ b/telephony/java/android/telephony/ims/RcsMessage.java
@@ -86,6 +86,11 @@
/**
* @hide
*/
+ protected final RcsControllerCall mRcsControllerCall;
+
+ /**
+ * @hide
+ */
protected final int mId;
@IntDef({
@@ -95,7 +100,8 @@
public @interface RcsMessageStatus {
}
- RcsMessage(int id) {
+ RcsMessage(RcsControllerCall rcsControllerCall, int id) {
+ mRcsControllerCall = rcsControllerCall;
mId = id;
}
@@ -115,7 +121,8 @@
* @see android.telephony.SubscriptionInfo#getSubscriptionId
*/
public int getSubscriptionId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageSubId(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageSubId(mId, isIncoming(), callingPackage));
}
/**
@@ -128,7 +135,9 @@
*/
@WorkerThread
public void setSubscriptionId(int subId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setMessageSubId(mId, isIncoming(), subId));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setMessageSubId(mId, isIncoming(), subId,
+ callingPackage));
}
/**
@@ -139,8 +148,9 @@
*/
@WorkerThread
public void setStatus(@RcsMessageStatus int rcsMessageStatus) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setMessageStatus(mId, isIncoming(), rcsMessageStatus));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setMessageStatus(mId, isIncoming(), rcsMessageStatus,
+ callingPackage));
}
/**
@@ -150,7 +160,8 @@
*/
@WorkerThread
public @RcsMessageStatus int getStatus() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageStatus(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageStatus(mId, isIncoming(), callingPackage));
}
/**
@@ -163,8 +174,9 @@
*/
@WorkerThread
public void setOriginationTimestamp(long timestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setMessageOriginationTimestamp(mId, isIncoming(), timestamp));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setMessageOriginationTimestamp(mId, isIncoming(),
+ timestamp, callingPackage));
}
/**
@@ -175,8 +187,9 @@
*/
@WorkerThread
public long getOriginationTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(
- iRcs -> iRcs.getMessageOriginationTimestamp(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageOriginationTimestamp(mId, isIncoming(),
+ callingPackage));
}
/**
@@ -189,8 +202,9 @@
*/
@WorkerThread
public void setRcsMessageId(String rcsMessageGlobalId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setGlobalMessageIdForMessage(mId, isIncoming(), rcsMessageGlobalId));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setGlobalMessageIdForMessage(mId, isIncoming(),
+ rcsMessageGlobalId, callingPackage));
}
/**
@@ -200,7 +214,9 @@
*/
@WorkerThread
public String getRcsMessageId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming(),
+ callingPackage));
}
/**
@@ -209,7 +225,9 @@
*/
@WorkerThread
public String getText() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getTextForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getTextForMessage(mId, isIncoming(),
+ callingPackage));
}
/**
@@ -220,18 +238,21 @@
*/
@WorkerThread
public void setText(String text) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setTextForMessage(mId, isIncoming(), text));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setTextForMessage(mId, isIncoming(), text,
+ callingPackage));
}
/**
* @return Returns the associated latitude for this message, or
* {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location.
- *
* @throws RcsMessageStoreException if the value could not be read from the storage
*/
@WorkerThread
public double getLatitude() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getLatitudeForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getLatitudeForMessage(mId, isIncoming(),
+ callingPackage));
}
/**
@@ -242,19 +263,21 @@
*/
@WorkerThread
public void setLatitude(double latitude) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setLatitudeForMessage(mId, isIncoming(), latitude));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setLatitudeForMessage(mId, isIncoming(), latitude,
+ callingPackage));
}
/**
* @return Returns the associated longitude for this message, or
* {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location.
- *
* @throws RcsMessageStoreException if the value could not be read from the storage
*/
@WorkerThread
public double getLongitude() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getLongitudeForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getLongitudeForMessage(mId, isIncoming(),
+ callingPackage));
}
/**
@@ -265,8 +288,9 @@
*/
@WorkerThread
public void setLongitude(double longitude) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setLongitudeForMessage(mId, isIncoming(), longitude));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setLongitudeForMessage(mId, isIncoming(), longitude,
+ callingPackage));
}
/**
@@ -282,8 +306,9 @@
public RcsFileTransferPart insertFileTransfer(
RcsFileTransferCreationParams fileTransferCreationParameters)
throws RcsMessageStoreException {
- return new RcsFileTransferPart(RcsControllerCall.call(
- iRcs -> iRcs.storeFileTransfer(mId, isIncoming(), fileTransferCreationParameters)));
+ return new RcsFileTransferPart(mRcsControllerCall, mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.storeFileTransfer(mId, isIncoming(),
+ fileTransferCreationParameters, callingPackage)));
}
/**
@@ -296,11 +321,12 @@
public Set<RcsFileTransferPart> getFileTransferParts() throws RcsMessageStoreException {
Set<RcsFileTransferPart> fileTransferParts = new HashSet<>();
- int[] fileTransferIds = RcsControllerCall.call(
- iRcs -> iRcs.getFileTransfersAttachedToMessage(mId, isIncoming()));
+ int[] fileTransferIds = mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransfersAttachedToMessage(mId, isIncoming(),
+ callingPackage));
for (int fileTransfer : fileTransferIds) {
- fileTransferParts.add(new RcsFileTransferPart(fileTransfer));
+ fileTransferParts.add(new RcsFileTransferPart(mRcsControllerCall, fileTransfer));
}
return Collections.unmodifiableSet(fileTransferParts);
@@ -319,8 +345,9 @@
return;
}
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.deleteFileTransfer(fileTransferPart.getId()));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.deleteFileTransfer(fileTransferPart.getId(),
+ callingPackage));
}
/**
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
index 5df929b..36bb78a 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
@@ -20,13 +20,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import com.android.ims.RcsTypeIdPair;
-
-import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
/**
* The result of a {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
@@ -35,23 +31,14 @@
*
* @hide
*/
-public final class RcsMessageQueryResult implements Parcelable {
- // The token to continue the query to get the next batch of results
- private RcsQueryContinuationToken mContinuationToken;
- // The message type and message ID pairs for all the messages in this query result
- private List<RcsTypeIdPair> mMessageTypeIdPairs;
+public final class RcsMessageQueryResult {
+ private final RcsControllerCall mRcsControllerCall;
+ private final RcsMessageQueryResultParcelable mRcsMessageQueryResultParcelable;
- /**
- * Internal constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
- * to create query results
- *
- * @hide
- */
- public RcsMessageQueryResult(
- RcsQueryContinuationToken continuationToken,
- List<RcsTypeIdPair> messageTypeIdPairs) {
- mContinuationToken = continuationToken;
- mMessageTypeIdPairs = messageTypeIdPairs;
+ RcsMessageQueryResult(RcsControllerCall rcsControllerCall,
+ RcsMessageQueryResultParcelable rcsMessageQueryResultParcelable) {
+ mRcsControllerCall = rcsControllerCall;
+ mRcsMessageQueryResultParcelable = rcsMessageQueryResultParcelable;
}
/**
@@ -61,7 +48,7 @@
*/
@Nullable
public RcsQueryContinuationToken getContinuationToken() {
- return mContinuationToken;
+ return mRcsMessageQueryResultParcelable.mContinuationToken;
}
/**
@@ -71,45 +58,10 @@
*/
@NonNull
public List<RcsMessage> getMessages() {
- List<RcsMessage> messages = new ArrayList<>();
- for (RcsTypeIdPair typeIdPair : mMessageTypeIdPairs) {
- if (typeIdPair.getType() == MESSAGE_TYPE_INCOMING) {
- messages.add(new RcsIncomingMessage(typeIdPair.getId()));
- } else {
- messages.add(new RcsOutgoingMessage(typeIdPair.getId()));
- }
- }
-
- return messages;
- }
-
- private RcsMessageQueryResult(Parcel in) {
- mContinuationToken = in.readParcelable(
- RcsQueryContinuationToken.class.getClassLoader());
- in.readTypedList(mMessageTypeIdPairs, RcsTypeIdPair.CREATOR);
- }
-
- public static final @android.annotation.NonNull Creator<RcsMessageQueryResult> CREATOR =
- new Creator<RcsMessageQueryResult>() {
- @Override
- public RcsMessageQueryResult createFromParcel(Parcel in) {
- return new RcsMessageQueryResult(in);
- }
-
- @Override
- public RcsMessageQueryResult[] newArray(int size) {
- return new RcsMessageQueryResult[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mContinuationToken, flags);
- dest.writeTypedList(mMessageTypeIdPairs);
+ return mRcsMessageQueryResultParcelable.mMessageTypeIdPairs.stream()
+ .map(typeIdPair -> typeIdPair.getType() == MESSAGE_TYPE_INCOMING
+ ? new RcsIncomingMessage(mRcsControllerCall, typeIdPair.getId())
+ : new RcsOutgoingMessage(mRcsControllerCall, typeIdPair.getId()))
+ .collect(Collectors.toList());
}
}
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
similarity index 93%
copy from telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
copy to telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
index a73ba50..86928bf 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsMessageQueryResult;
+parcelable RcsMessageQueryResultParcelable;
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java
new file mode 100644
index 0000000..4972f9b
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.ims.RcsTypeIdPair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @hide - used only for internal communication with the ircs service
+ */
+public class RcsMessageQueryResultParcelable implements Parcelable {
+ // The token to continue the query to get the next batch of results
+ final RcsQueryContinuationToken mContinuationToken;
+ // The message type and message ID pairs for all the messages in this query result
+ final List<RcsTypeIdPair> mMessageTypeIdPairs;
+
+ public RcsMessageQueryResultParcelable(
+ RcsQueryContinuationToken continuationToken,
+ List<RcsTypeIdPair> messageTypeIdPairs) {
+ mContinuationToken = continuationToken;
+ mMessageTypeIdPairs = messageTypeIdPairs;
+ }
+
+ private RcsMessageQueryResultParcelable(Parcel in) {
+ mContinuationToken = in.readParcelable(
+ RcsQueryContinuationToken.class.getClassLoader());
+
+ mMessageTypeIdPairs = new ArrayList<>();
+ in.readTypedList(mMessageTypeIdPairs, RcsTypeIdPair.CREATOR);
+ }
+
+ public static final Creator<RcsMessageQueryResultParcelable> CREATOR =
+ new Creator<RcsMessageQueryResultParcelable>() {
+ @Override
+ public RcsMessageQueryResultParcelable createFromParcel(Parcel in) {
+ return new RcsMessageQueryResultParcelable(in);
+ }
+
+ @Override
+ public RcsMessageQueryResultParcelable[] newArray(int size) {
+ return new RcsMessageQueryResultParcelable[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mContinuationToken, flags);
+ dest.writeTypedList(mMessageTypeIdPairs);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsMessageStore.java b/telephony/java/android/telephony/ims/RcsMessageStore.java
index 3111652..d112798 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStore.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStore.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.WorkerThread;
+import android.content.Context;
import android.net.Uri;
import java.util.List;
@@ -30,6 +31,12 @@
* @hide
*/
public class RcsMessageStore {
+ RcsControllerCall mRcsControllerCall;
+
+ RcsMessageStore(Context context) {
+ mRcsControllerCall = new RcsControllerCall(context);
+ }
+
/**
* Returns the first chunk of existing {@link RcsThread}s in the common storage.
*
@@ -41,7 +48,10 @@
@NonNull
public RcsThreadQueryResult getRcsThreads(@Nullable RcsThreadQueryParams queryParameters)
throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getRcsThreads(queryParameters));
+ return new RcsThreadQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getRcsThreads(queryParameters,
+ callingPackage)));
}
/**
@@ -55,7 +65,10 @@
@NonNull
public RcsThreadQueryResult getRcsThreads(@NonNull RcsQueryContinuationToken continuationToken)
throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getRcsThreadsWithToken(continuationToken));
+ return new RcsThreadQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getRcsThreadsWithToken(continuationToken,
+ callingPackage)));
}
/**
@@ -70,7 +83,10 @@
public RcsParticipantQueryResult getRcsParticipants(
@Nullable RcsParticipantQueryParams queryParameters)
throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getParticipants(queryParameters));
+ return new RcsParticipantQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getParticipants(queryParameters,
+ callingPackage)));
}
/**
@@ -86,21 +102,26 @@
public RcsParticipantQueryResult getRcsParticipants(
@NonNull RcsQueryContinuationToken continuationToken)
throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getParticipantsWithToken(continuationToken));
+ return new RcsParticipantQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getParticipantsWithToken(continuationToken,
+ callingPackage)));
}
/**
* Returns the first chunk of existing {@link RcsMessage}s in the common storage.
*
- * @param queryParameters Parameters to specify to return a subset of all RcsMessages.
- * Passing a value of null will return all messages.
+ * @param queryParams Parameters to specify to return a subset of all RcsMessages.
+ * Passing a value of null will return all messages.
* @throws RcsMessageStoreException if the query could not be completed on the storage
*/
@WorkerThread
@NonNull
public RcsMessageQueryResult getRcsMessages(
- @Nullable RcsMessageQueryParams queryParameters) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessages(queryParameters));
+ @Nullable RcsMessageQueryParams queryParams) throws RcsMessageStoreException {
+ return new RcsMessageQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessages(queryParams, callingPackage)));
}
/**
@@ -114,22 +135,26 @@
@NonNull
public RcsMessageQueryResult getRcsMessages(
@NonNull RcsQueryContinuationToken continuationToken) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessagesWithToken(continuationToken));
+ return new RcsMessageQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessagesWithToken(continuationToken,
+ callingPackage)));
}
/**
* Returns the first chunk of existing {@link RcsEvent}s in the common storage.
*
* @param queryParams Parameters to specify to return a subset of all RcsEvents.
- * Passing a value of null will return all events.
+ * Passing a value of null will return all events.
* @throws RcsMessageStoreException if the query could not be completed on the storage
*/
@WorkerThread
@NonNull
public RcsEventQueryResult getRcsEvents(
@Nullable RcsEventQueryParams queryParams) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getEvents(queryParams))
- .getRcsEventQueryResult();
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getEvents(queryParams, callingPackage))
+ .getRcsEventQueryResult(mRcsControllerCall);
}
/**
@@ -143,16 +168,17 @@
@NonNull
public RcsEventQueryResult getRcsEvents(
@NonNull RcsQueryContinuationToken continuationToken) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getEventsWithToken(continuationToken))
- .getRcsEventQueryResult();
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getEventsWithToken(continuationToken,
+ callingPackage))
+ .getRcsEventQueryResult(mRcsControllerCall);
}
/**
* Persists an {@link RcsEvent} to common storage.
*
- * @param persistableEvent The {@link RcsEvent} to persist into storage.
+ * @param rcsEvent The {@link RcsEvent} to persist into storage.
* @throws RcsMessageStoreException if the query could not be completed on the storage
- *
* @see RcsGroupThreadNameChangedEvent
* @see RcsGroupThreadIconChangedEvent
* @see RcsGroupThreadParticipantJoinedEvent
@@ -161,8 +187,8 @@
*/
@WorkerThread
@NonNull
- public void persistRcsEvent(RcsEvent persistableEvent) throws RcsMessageStoreException {
- persistableEvent.persist();
+ public void persistRcsEvent(RcsEvent rcsEvent) throws RcsMessageStoreException {
+ rcsEvent.persist(mRcsControllerCall);
}
/**
@@ -177,7 +203,10 @@
public Rcs1To1Thread createRcs1To1Thread(@NonNull RcsParticipant recipient)
throws RcsMessageStoreException {
return new Rcs1To1Thread(
- RcsControllerCall.call(iRcs -> iRcs.createRcs1To1Thread(recipient.getId())));
+ mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.createRcs1To1Thread(recipient.getId(),
+ callingPackage)));
}
/**
@@ -199,8 +228,12 @@
}
int[] finalRecipientIds = recipientIds;
- return new RcsGroupThread(RcsControllerCall.call(
- iRcs -> iRcs.createGroupThread(finalRecipientIds, groupName, groupIcon)));
+
+ int threadId = mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.createGroupThread(finalRecipientIds, groupName,
+ groupIcon, callingPackage));
+
+ return new RcsGroupThread(mRcsControllerCall, threadId);
}
/**
@@ -215,8 +248,9 @@
return;
}
- boolean isDeleteSucceeded = RcsControllerCall.call(
- iRcs -> iRcs.deleteThread(thread.getThreadId(), thread.getThreadType()));
+ boolean isDeleteSucceeded = mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.deleteThread(thread.getThreadId(),
+ thread.getThreadType(), callingPackage));
if (!isDeleteSucceeded) {
throw new RcsMessageStoreException("Could not delete RcsThread");
@@ -234,7 +268,8 @@
@NonNull
public RcsParticipant createRcsParticipant(String canonicalAddress, @Nullable String alias)
throws RcsMessageStoreException {
- return new RcsParticipant(
- RcsControllerCall.call(iRcs -> iRcs.createRcsParticipant(canonicalAddress, alias)));
+ return new RcsParticipant(mRcsControllerCall, mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.createRcsParticipant(canonicalAddress, alias,
+ callingPackage)));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
index 1b4bfe5..7080ec6 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
@@ -27,8 +27,8 @@
* @hide
*/
public class RcsOutgoingMessage extends RcsMessage {
- RcsOutgoingMessage(int id) {
- super(id);
+ RcsOutgoingMessage(RcsControllerCall rcsControllerCall, int id) {
+ super(rcsControllerCall, id);
}
/**
@@ -45,12 +45,13 @@
int[] deliveryParticipants;
List<RcsOutgoingMessageDelivery> messageDeliveries = new ArrayList<>();
- deliveryParticipants = RcsControllerCall.call(
- iRcs -> iRcs.getMessageRecipients(mId));
+ deliveryParticipants = mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageRecipients(mId, callingPackage));
if (deliveryParticipants != null) {
for (Integer deliveryParticipant : deliveryParticipants) {
- messageDeliveries.add(new RcsOutgoingMessageDelivery(deliveryParticipant, mId));
+ messageDeliveries.add(new RcsOutgoingMessageDelivery(
+ mRcsControllerCall, deliveryParticipant, mId));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
index 2db49c6..df4a3e4 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
@@ -25,6 +25,7 @@
* @hide
*/
public class RcsOutgoingMessageDelivery {
+ private final RcsControllerCall mRcsControllerCall;
// The participant that this delivery is intended for
private final int mRecipientId;
// The message this delivery is associated with
@@ -35,7 +36,9 @@
*
* @hide
*/
- RcsOutgoingMessageDelivery(int recipientId, int messageId) {
+ RcsOutgoingMessageDelivery(
+ RcsControllerCall rcsControllerCall, int recipientId, int messageId) {
+ mRcsControllerCall = rcsControllerCall;
mRecipientId = recipientId;
mRcsOutgoingMessageId = messageId;
}
@@ -49,8 +52,9 @@
*/
@WorkerThread
public void setDeliveredTimestamp(long deliveredTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryDeliveredTimestamp(
- mRcsOutgoingMessageId, mRecipientId, deliveredTimestamp));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setOutgoingDeliveryDeliveredTimestamp(
+ mRcsOutgoingMessageId, mRecipientId, deliveredTimestamp, callingPackage));
}
/**
@@ -61,8 +65,9 @@
*/
@WorkerThread
public long getDeliveredTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getOutgoingDeliveryDeliveredTimestamp(
- mRcsOutgoingMessageId, mRecipientId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getOutgoingDeliveryDeliveredTimestamp(
+ mRcsOutgoingMessageId, mRecipientId, callingPackage));
}
/**
@@ -74,8 +79,9 @@
*/
@WorkerThread
public void setSeenTimestamp(long seenTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliverySeenTimestamp(
- mRcsOutgoingMessageId, mRecipientId, seenTimestamp));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setOutgoingDeliverySeenTimestamp(
+ mRcsOutgoingMessageId, mRecipientId, seenTimestamp, callingPackage));
}
/**
@@ -86,8 +92,9 @@
*/
@WorkerThread
public long getSeenTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(
- iRcs -> iRcs.getOutgoingDeliverySeenTimestamp(mRcsOutgoingMessageId, mRecipientId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getOutgoingDeliverySeenTimestamp(
+ mRcsOutgoingMessageId, mRecipientId, callingPackage));
}
/**
@@ -99,8 +106,9 @@
*/
@WorkerThread
public void setStatus(@RcsMessage.RcsMessageStatus int status) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryStatus(
- mRcsOutgoingMessageId, mRecipientId, status));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setOutgoingDeliveryStatus(
+ mRcsOutgoingMessageId, mRecipientId, status, callingPackage));
}
/**
@@ -109,8 +117,9 @@
*/
@WorkerThread
public @RcsMessage.RcsMessageStatus int getStatus() throws RcsMessageStoreException {
- return RcsControllerCall.call(
- iRcs -> iRcs.getOutgoingDeliveryStatus(mRcsOutgoingMessageId, mRecipientId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getOutgoingDeliveryStatus(mRcsOutgoingMessageId,
+ mRecipientId, callingPackage));
}
/**
@@ -118,7 +127,7 @@
*/
@NonNull
public RcsParticipant getRecipient() {
- return new RcsParticipant(mRecipientId);
+ return new RcsParticipant(mRcsControllerCall, mRecipientId);
}
/**
@@ -126,6 +135,6 @@
*/
@NonNull
public RcsOutgoingMessage getMessage() {
- return new RcsOutgoingMessage(mRcsOutgoingMessageId);
+ return new RcsOutgoingMessage(mRcsControllerCall, mRcsOutgoingMessageId);
}
}
diff --git a/telephony/java/android/telephony/ims/RcsParticipant.java b/telephony/java/android/telephony/ims/RcsParticipant.java
index bcf134a..8512e96 100644
--- a/telephony/java/android/telephony/ims/RcsParticipant.java
+++ b/telephony/java/android/telephony/ims/RcsParticipant.java
@@ -24,8 +24,9 @@
* @hide
*/
public class RcsParticipant {
+ private final RcsControllerCall mRcsControllerCall;
// The row ID of this participant in the database
- private int mId;
+ private final int mId;
/**
* Constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
@@ -33,7 +34,8 @@
*
* @hide
*/
- public RcsParticipant(int id) {
+ public RcsParticipant(RcsControllerCall rcsControllerCall, int id) {
+ mRcsControllerCall = rcsControllerCall;
mId = id;
}
@@ -45,7 +47,9 @@
@Nullable
@WorkerThread
public String getCanonicalAddress() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantCanonicalAddress(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getRcsParticipantCanonicalAddress(mId,
+ callingPackage));
}
/**
@@ -57,7 +61,8 @@
@Nullable
@WorkerThread
public String getAlias() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantAlias(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getRcsParticipantAlias(mId, callingPackage));
}
/**
@@ -70,7 +75,8 @@
*/
@WorkerThread
public void setAlias(String alias) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setRcsParticipantAlias(mId, alias));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setRcsParticipantAlias(mId, alias, callingPackage));
}
/**
@@ -82,7 +88,8 @@
@Nullable
@WorkerThread
public String getContactId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantContactId(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getRcsParticipantContactId(mId, callingPackage));
}
/**
@@ -95,7 +102,9 @@
*/
@WorkerThread
public void setContactId(String contactId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setRcsParticipantContactId(mId, contactId));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setRcsParticipantContactId(mId, contactId,
+ callingPackage));
}
@Override
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
index 61801f3..865bc05 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
@@ -69,8 +69,8 @@
* @hide - not meant for public use.
*/
@Override
- public void persist() throws RcsMessageStoreException {
- RcsControllerCall.call(iRcs -> iRcs.createParticipantAliasChangedEvent(
- getTimestamp(), getParticipant().getId(), getNewAlias()));
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+ rcsControllerCall.call((iRcs, callingPackage) -> iRcs.createParticipantAliasChangedEvent(
+ getTimestamp(), getParticipant().getId(), getNewAlias(), callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
index b29896c..43b918c 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
@@ -41,9 +41,9 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsParticipantAliasChangedEvent createRcsEvent() {
+ public RcsParticipantAliasChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
return new RcsParticipantAliasChangedEvent(
- mTimestamp, new RcsParticipant(mParticipantId), mNewAlias);
+ mTimestamp, new RcsParticipant(rcsControllerCall, mParticipantId), mNewAlias);
}
public static final @NonNull Creator<RcsParticipantAliasChangedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.aidl b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.aidl
deleted file mode 100644
index db5c00c..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsParticipantQueryResult;
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
index 3e5c231..0721dfd 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
@@ -18,11 +18,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
/**
* The result of a {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)}
@@ -31,23 +29,15 @@
*
* @hide
*/
-public final class RcsParticipantQueryResult implements Parcelable {
- // A token for the caller to continue their query for the next batch of results
- private RcsQueryContinuationToken mContinuationToken;
- // The list of participant IDs returned with this query
- private List<Integer> mParticipants;
+public final class RcsParticipantQueryResult {
+ private final RcsControllerCall mRcsControllerCall;
+ private final RcsParticipantQueryResultParcelable mRcsParticipantQueryResultParcelable;
- /**
- * Internal constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
- * to create query results
- *
- * @hide
- */
- public RcsParticipantQueryResult(
- RcsQueryContinuationToken continuationToken,
- List<Integer> participants) {
- mContinuationToken = continuationToken;
- mParticipants = participants;
+ RcsParticipantQueryResult(
+ RcsControllerCall rcsControllerCall,
+ RcsParticipantQueryResultParcelable rcsParticipantQueryResultParcelable) {
+ mRcsControllerCall = rcsControllerCall;
+ mRcsParticipantQueryResultParcelable = rcsParticipantQueryResultParcelable;
}
/**
@@ -57,7 +47,7 @@
*/
@Nullable
public RcsQueryContinuationToken getContinuationToken() {
- return mContinuationToken;
+ return mRcsParticipantQueryResultParcelable.mContinuationToken;
}
/**
@@ -67,39 +57,8 @@
*/
@NonNull
public List<RcsParticipant> getParticipants() {
- List<RcsParticipant> participantList = new ArrayList<>();
- for (Integer participantId : mParticipants) {
- participantList.add(new RcsParticipant(participantId));
- }
-
- return participantList;
- }
-
- private RcsParticipantQueryResult(Parcel in) {
- mContinuationToken = in.readParcelable(
- RcsQueryContinuationToken.class.getClassLoader());
- }
-
- public static final @android.annotation.NonNull Creator<RcsParticipantQueryResult> CREATOR =
- new Creator<RcsParticipantQueryResult>() {
- @Override
- public RcsParticipantQueryResult createFromParcel(Parcel in) {
- return new RcsParticipantQueryResult(in);
- }
-
- @Override
- public RcsParticipantQueryResult[] newArray(int size) {
- return new RcsParticipantQueryResult[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mContinuationToken, flags);
+ return mRcsParticipantQueryResultParcelable.mParticipantIds.stream()
+ .map(participantId -> new RcsParticipant(mRcsControllerCall, participantId))
+ .collect(Collectors.toList());
}
}
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl b/telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.aidl
similarity index 92%
copy from telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
copy to telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.aidl
index a73ba50..54c72e7 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsMessageQueryResult;
+parcelable RcsParticipantQueryResultParcelable;
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.java b/telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.java
new file mode 100644
index 0000000..239b0e9
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryResultParcelable.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @hide
+ */
+public final class RcsParticipantQueryResultParcelable implements Parcelable {
+ final RcsQueryContinuationToken mContinuationToken;
+ final List<Integer> mParticipantIds;
+
+ public RcsParticipantQueryResultParcelable(
+ RcsQueryContinuationToken continuationToken,
+ List<Integer> participantIds) {
+ mContinuationToken = continuationToken;
+ mParticipantIds = participantIds;
+ }
+
+ private RcsParticipantQueryResultParcelable(Parcel in) {
+ mContinuationToken = in.readParcelable(RcsQueryContinuationToken.class.getClassLoader());
+ mParticipantIds = new ArrayList<>();
+ in.readList(mParticipantIds, Integer.class.getClassLoader());
+ }
+
+ public static final Parcelable.Creator<RcsParticipantQueryResultParcelable> CREATOR =
+ new Parcelable.Creator<RcsParticipantQueryResultParcelable>() {
+ @Override
+ public RcsParticipantQueryResultParcelable createFromParcel(Parcel in) {
+ return new RcsParticipantQueryResultParcelable(in);
+ }
+
+ @Override
+ public RcsParticipantQueryResultParcelable[] newArray(int size) {
+ return new RcsParticipantQueryResultParcelable[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mContinuationToken, flags);
+ dest.writeList(mParticipantIds);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsThread.java b/telephony/java/android/telephony/ims/RcsThread.java
index cf1dc76..efb2cca 100644
--- a/telephony/java/android/telephony/ims/RcsThread.java
+++ b/telephony/java/android/telephony/ims/RcsThread.java
@@ -33,6 +33,7 @@
public abstract class RcsThread {
/**
* The rcs_participant_thread_id that represents this thread in the database
+ *
* @hide
*/
protected int mThreadId;
@@ -40,8 +41,14 @@
/**
* @hide
*/
- protected RcsThread(int threadId) {
+ protected final RcsControllerCall mRcsControllerCall;
+
+ /**
+ * @hide
+ */
+ protected RcsThread(RcsControllerCall rcsControllerCall, int threadId) {
mThreadId = threadId;
+ mRcsControllerCall = rcsControllerCall;
}
/**
@@ -51,7 +58,8 @@
@WorkerThread
@NonNull
public RcsMessageSnippet getSnippet() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageSnippet(mThreadId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageSnippet(mThreadId, callingPackage));
}
/**
@@ -64,8 +72,10 @@
public RcsIncomingMessage addIncomingMessage(
@NonNull RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams)
throws RcsMessageStoreException {
- return new RcsIncomingMessage(RcsControllerCall.call(iRcs -> iRcs.addIncomingMessage(
- mThreadId, rcsIncomingMessageCreationParams)));
+ int messageId = mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.addIncomingMessage(mThreadId,
+ rcsIncomingMessageCreationParams, callingPackage));
+ return new RcsIncomingMessage(mRcsControllerCall, messageId);
}
/**
@@ -78,10 +88,10 @@
public RcsOutgoingMessage addOutgoingMessage(
@NonNull RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams)
throws RcsMessageStoreException {
- int messageId = RcsControllerCall.call(iRcs -> iRcs.addOutgoingMessage(
- mThreadId, rcsOutgoingMessageCreationParams));
+ int messageId = mRcsControllerCall.call((iRcs, callingPackage) -> iRcs.addOutgoingMessage(
+ mThreadId, rcsOutgoingMessageCreationParams, callingPackage));
- return new RcsOutgoingMessage(messageId);
+ return new RcsOutgoingMessage(mRcsControllerCall, messageId);
}
/**
@@ -92,9 +102,10 @@
*/
@WorkerThread
public void deleteMessage(@NonNull RcsMessage rcsMessage) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.deleteMessage(rcsMessage.getId(), rcsMessage.isIncoming(), mThreadId,
- isGroup()));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.deleteMessage(rcsMessage.getId(),
+ rcsMessage.isIncoming(), mThreadId,
+ isGroup(), callingPackage));
}
/**
@@ -108,9 +119,11 @@
@WorkerThread
@NonNull
public RcsMessageQueryResult getMessages() throws RcsMessageStoreException {
- RcsMessageQueryParams queryParameters =
+ RcsMessageQueryParams queryParams =
new RcsMessageQueryParams.Builder().setThread(this).build();
- return RcsControllerCall.call(iRcs -> iRcs.getMessages(queryParameters));
+ return new RcsMessageQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessages(queryParams, callingPackage)));
}
/**
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResult.aidl b/telephony/java/android/telephony/ims/RcsThreadQueryResult.aidl
deleted file mode 100644
index b1d5cf4..0000000
--- a/telephony/java/android/telephony/ims/RcsThreadQueryResult.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsThreadQueryResult;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
index c2c2d3a..3de25de 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
@@ -20,13 +20,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import com.android.ims.RcsTypeIdPair;
-
-import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
+
/**
* The result of a {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)}
@@ -35,23 +32,14 @@
*
* @hide
*/
-public final class RcsThreadQueryResult implements Parcelable {
- // A token for the caller to continue their query for the next batch of results
- private RcsQueryContinuationToken mContinuationToken;
- // The list of thread IDs returned with this query
- private List<RcsTypeIdPair> mRcsThreadIds;
+public final class RcsThreadQueryResult {
+ private final RcsControllerCall mRcsControllerCall;
+ private final RcsThreadQueryResultParcelable mRcsThreadQueryResultParcelable;
- /**
- * Internal constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
- * to create query results
- *
- * @hide
- */
- public RcsThreadQueryResult(
- RcsQueryContinuationToken continuationToken,
- List<RcsTypeIdPair> rcsThreadIds) {
- mContinuationToken = continuationToken;
- mRcsThreadIds = rcsThreadIds;
+ RcsThreadQueryResult(RcsControllerCall rcsControllerCall,
+ RcsThreadQueryResultParcelable rcsThreadQueryResultParcelable) {
+ mRcsControllerCall = rcsControllerCall;
+ mRcsThreadQueryResultParcelable = rcsThreadQueryResultParcelable;
}
/**
@@ -61,7 +49,7 @@
*/
@Nullable
public RcsQueryContinuationToken getContinuationToken() {
- return mContinuationToken;
+ return mRcsThreadQueryResultParcelable.mContinuationToken;
}
/**
@@ -71,47 +59,10 @@
*/
@NonNull
public List<RcsThread> getThreads() {
- List<RcsThread> rcsThreads = new ArrayList<>();
-
- for (RcsTypeIdPair typeIdPair : mRcsThreadIds) {
- if (typeIdPair.getType() == THREAD_TYPE_1_TO_1) {
- rcsThreads.add(new Rcs1To1Thread(typeIdPair.getId()));
- } else {
- rcsThreads.add(new RcsGroupThread(typeIdPair.getId()));
- }
- }
-
- return rcsThreads;
- }
-
- private RcsThreadQueryResult(Parcel in) {
- mContinuationToken = in.readParcelable(
- RcsQueryContinuationToken.class.getClassLoader());
- mRcsThreadIds = new ArrayList<>();
- in.readList(mRcsThreadIds, Integer.class.getClassLoader());
- }
-
- public static final @android.annotation.NonNull Creator<RcsThreadQueryResult> CREATOR =
- new Creator<RcsThreadQueryResult>() {
- @Override
- public RcsThreadQueryResult createFromParcel(Parcel in) {
- return new RcsThreadQueryResult(in);
- }
-
- @Override
- public RcsThreadQueryResult[] newArray(int size) {
- return new RcsThreadQueryResult[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mContinuationToken, flags);
- dest.writeList(mRcsThreadIds);
+ return mRcsThreadQueryResultParcelable.mRcsThreadIds.stream()
+ .map(typeIdPair -> typeIdPair.getType() == THREAD_TYPE_1_TO_1
+ ? new Rcs1To1Thread(mRcsControllerCall, typeIdPair.getId())
+ : new RcsGroupThread(mRcsControllerCall, typeIdPair.getId()))
+ .collect(Collectors.toList());
}
}
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl b/telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.aidl
similarity index 93%
rename from telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
rename to telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.aidl
index a73ba50..05bd61d 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsMessageQueryResult;
+parcelable RcsThreadQueryResultParcelable;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.java b/telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.java
new file mode 100644
index 0000000..89dd1d4
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryResultParcelable.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.ims.RcsTypeIdPair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @hide
+ */
+public final class RcsThreadQueryResultParcelable implements Parcelable {
+ final RcsQueryContinuationToken mContinuationToken;
+ final List<RcsTypeIdPair> mRcsThreadIds;
+
+ public RcsThreadQueryResultParcelable(
+ RcsQueryContinuationToken continuationToken,
+ List<RcsTypeIdPair> rcsThreadIds) {
+ mContinuationToken = continuationToken;
+ mRcsThreadIds = rcsThreadIds;
+ }
+
+ private RcsThreadQueryResultParcelable(Parcel in) {
+ mContinuationToken = in.readParcelable(RcsQueryContinuationToken.class.getClassLoader());
+ mRcsThreadIds = new ArrayList<>();
+ in.readList(mRcsThreadIds, RcsTypeIdPair.class.getClassLoader());
+ }
+
+ public static final Parcelable.Creator<RcsThreadQueryResultParcelable> CREATOR =
+ new Parcelable.Creator<RcsThreadQueryResultParcelable>() {
+ @Override
+ public RcsThreadQueryResultParcelable createFromParcel(Parcel in) {
+ return new RcsThreadQueryResultParcelable(in);
+ }
+
+ @Override
+ public RcsThreadQueryResultParcelable[] newArray(int size) {
+ return new RcsThreadQueryResultParcelable[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mContinuationToken, flags);
+ dest.writeList(mRcsThreadIds);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IRcs.aidl b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
index 6ab01c2..9ee15da 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcs.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
@@ -23,13 +23,13 @@
import android.telephony.ims.RcsIncomingMessageCreationParams;
import android.telephony.ims.RcsMessageSnippet;
import android.telephony.ims.RcsMessageQueryParams;
-import android.telephony.ims.RcsMessageQueryResult;
+import android.telephony.ims.RcsMessageQueryResultParcelable;
import android.telephony.ims.RcsOutgoingMessageCreationParams;
import android.telephony.ims.RcsParticipantQueryParams;
-import android.telephony.ims.RcsParticipantQueryResult;
+import android.telephony.ims.RcsParticipantQueryResultParcelable;
import android.telephony.ims.RcsQueryContinuationToken;
import android.telephony.ims.RcsThreadQueryParams;
-import android.telephony.ims.RcsThreadQueryResult;
+import android.telephony.ims.RcsThreadQueryResultParcelable;
/**
* RPC definition between RCS storage APIs and phone process.
@@ -39,34 +39,34 @@
/////////////////////////
// RcsMessageStore APIs
/////////////////////////
- RcsThreadQueryResult getRcsThreads(in RcsThreadQueryParams queryParams);
+ RcsThreadQueryResultParcelable getRcsThreads(in RcsThreadQueryParams queryParams, String callingPackage);
- RcsThreadQueryResult getRcsThreadsWithToken(
- in RcsQueryContinuationToken continuationToken);
+ RcsThreadQueryResultParcelable getRcsThreadsWithToken(
+ in RcsQueryContinuationToken continuationToken, String callingPackage);
- RcsParticipantQueryResult getParticipants(in RcsParticipantQueryParams queryParams);
+ RcsParticipantQueryResultParcelable getParticipants(in RcsParticipantQueryParams queryParams, String callingPackage);
- RcsParticipantQueryResult getParticipantsWithToken(
- in RcsQueryContinuationToken continuationToken);
+ RcsParticipantQueryResultParcelable getParticipantsWithToken(
+ in RcsQueryContinuationToken continuationToken, String callingPackage);
- RcsMessageQueryResult getMessages(in RcsMessageQueryParams queryParams);
+ RcsMessageQueryResultParcelable getMessages(in RcsMessageQueryParams queryParams, String callingPackage);
- RcsMessageQueryResult getMessagesWithToken(
- in RcsQueryContinuationToken continuationToken);
+ RcsMessageQueryResultParcelable getMessagesWithToken(
+ in RcsQueryContinuationToken continuationToken, String callingPackage);
- RcsEventQueryResultDescriptor getEvents(in RcsEventQueryParams queryParams);
+ RcsEventQueryResultDescriptor getEvents(in RcsEventQueryParams queryParams, String callingPackage);
RcsEventQueryResultDescriptor getEventsWithToken(
- in RcsQueryContinuationToken continuationToken);
+ in RcsQueryContinuationToken continuationToken, String callingPackage);
// returns true if the thread was successfully deleted
- boolean deleteThread(int threadId, int threadType);
+ boolean deleteThread(int threadId, int threadType, String callingPackage);
// Creates an Rcs1To1Thread and returns its row ID
- int createRcs1To1Thread(int participantId);
+ int createRcs1To1Thread(int participantId, String callingPackage);
// Creates an RcsGroupThread and returns its row ID
- int createGroupThread(in int[] participantIds, String groupName, in Uri groupIcon);
+ int createGroupThread(in int[] participantIds, String groupName, in Uri groupIcon, String callingPackage);
/////////////////////////
// RcsThread APIs
@@ -74,128 +74,128 @@
// Creates a new RcsIncomingMessage on the given thread and returns its row ID
int addIncomingMessage(int rcsThreadId,
- in RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams);
+ in RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams, String callingPackage);
// Creates a new RcsOutgoingMessage on the given thread and returns its row ID
int addOutgoingMessage(int rcsThreadId,
- in RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams);
+ in RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams, String callingPackage);
// TODO: modify RcsProvider URI's to allow deleting a message without specifying its thread
- void deleteMessage(int rcsMessageId, boolean isIncoming, int rcsThreadId, boolean isGroup);
+ void deleteMessage(int rcsMessageId, boolean isIncoming, int rcsThreadId, boolean isGroup, String callingPackage);
- RcsMessageSnippet getMessageSnippet(int rcsThreadId);
+ RcsMessageSnippet getMessageSnippet(int rcsThreadId, String callingPackage);
/////////////////////////
// Rcs1To1Thread APIs
/////////////////////////
- void set1To1ThreadFallbackThreadId(int rcsThreadId, long fallbackId);
+ void set1To1ThreadFallbackThreadId(int rcsThreadId, long fallbackId, String callingPackage);
- long get1To1ThreadFallbackThreadId(int rcsThreadId);
+ long get1To1ThreadFallbackThreadId(int rcsThreadId, String callingPackage);
- int get1To1ThreadOtherParticipantId(int rcsThreadId);
+ int get1To1ThreadOtherParticipantId(int rcsThreadId, String callingPackage);
/////////////////////////
// RcsGroupThread APIs
/////////////////////////
- void setGroupThreadName(int rcsThreadId, String groupName);
+ void setGroupThreadName(int rcsThreadId, String groupName, String callingPackage);
- String getGroupThreadName(int rcsThreadId);
+ String getGroupThreadName(int rcsThreadId, String callingPackage);
- void setGroupThreadIcon(int rcsThreadId, in Uri groupIcon);
+ void setGroupThreadIcon(int rcsThreadId, in Uri groupIcon, String callingPackage);
- Uri getGroupThreadIcon(int rcsThreadId);
+ Uri getGroupThreadIcon(int rcsThreadId, String callingPackage);
- void setGroupThreadOwner(int rcsThreadId, int participantId);
+ void setGroupThreadOwner(int rcsThreadId, int participantId, String callingPackage);
- int getGroupThreadOwner(int rcsThreadId);
+ int getGroupThreadOwner(int rcsThreadId, String callingPackage);
- void setGroupThreadConferenceUri(int rcsThreadId, in Uri conferenceUri);
+ void setGroupThreadConferenceUri(int rcsThreadId, in Uri conferenceUri, String callingPackage);
- Uri getGroupThreadConferenceUri(int rcsThreadId);
+ Uri getGroupThreadConferenceUri(int rcsThreadId, String callingPackage);
- void addParticipantToGroupThread(int rcsThreadId, int participantId);
+ void addParticipantToGroupThread(int rcsThreadId, int participantId, String callingPackage);
- void removeParticipantFromGroupThread(int rcsThreadId, int participantId);
+ void removeParticipantFromGroupThread(int rcsThreadId, int participantId, String callingPackage);
/////////////////////////
// RcsParticipant APIs
/////////////////////////
// Creates a new RcsParticipant and returns its rowId
- int createRcsParticipant(String canonicalAddress, String alias);
+ int createRcsParticipant(String canonicalAddress, String alias, String callingPackage);
- String getRcsParticipantCanonicalAddress(int participantId);
+ String getRcsParticipantCanonicalAddress(int participantId, String callingPackage);
- String getRcsParticipantAlias(int participantId);
+ String getRcsParticipantAlias(int participantId, String callingPackage);
- void setRcsParticipantAlias(int id, String alias);
+ void setRcsParticipantAlias(int id, String alias, String callingPackage);
- String getRcsParticipantContactId(int participantId);
+ String getRcsParticipantContactId(int participantId, String callingPackage);
- void setRcsParticipantContactId(int participantId, String contactId);
+ void setRcsParticipantContactId(int participantId, String contactId, String callingPackage);
/////////////////////////
// RcsMessage APIs
/////////////////////////
- void setMessageSubId(int messageId, boolean isIncoming, int subId);
+ void setMessageSubId(int messageId, boolean isIncoming, int subId, String callingPackage);
- int getMessageSubId(int messageId, boolean isIncoming);
+ int getMessageSubId(int messageId, boolean isIncoming, String callingPackage);
- void setMessageStatus(int messageId, boolean isIncoming, int status);
+ void setMessageStatus(int messageId, boolean isIncoming, int status, String callingPackage);
- int getMessageStatus(int messageId, boolean isIncoming);
+ int getMessageStatus(int messageId, boolean isIncoming, String callingPackage);
- void setMessageOriginationTimestamp(int messageId, boolean isIncoming, long originationTimestamp);
+ void setMessageOriginationTimestamp(int messageId, boolean isIncoming, long originationTimestamp, String callingPackage);
- long getMessageOriginationTimestamp(int messageId, boolean isIncoming);
+ long getMessageOriginationTimestamp(int messageId, boolean isIncoming, String callingPackage);
- void setGlobalMessageIdForMessage(int messageId, boolean isIncoming, String globalId);
+ void setGlobalMessageIdForMessage(int messageId, boolean isIncoming, String globalId, String callingPackage);
- String getGlobalMessageIdForMessage(int messageId, boolean isIncoming);
+ String getGlobalMessageIdForMessage(int messageId, boolean isIncoming, String callingPackage);
- void setMessageArrivalTimestamp(int messageId, boolean isIncoming, long arrivalTimestamp);
+ void setMessageArrivalTimestamp(int messageId, boolean isIncoming, long arrivalTimestamp, String callingPackage);
- long getMessageArrivalTimestamp(int messageId, boolean isIncoming);
+ long getMessageArrivalTimestamp(int messageId, boolean isIncoming, String callingPackage);
- void setMessageSeenTimestamp(int messageId, boolean isIncoming, long seenTimestamp);
+ void setMessageSeenTimestamp(int messageId, boolean isIncoming, long seenTimestamp, String callingPackage);
- long getMessageSeenTimestamp(int messageId, boolean isIncoming);
+ long getMessageSeenTimestamp(int messageId, boolean isIncoming, String callingPackage);
- void setTextForMessage(int messageId, boolean isIncoming, String text);
+ void setTextForMessage(int messageId, boolean isIncoming, String text, String callingPackage);
- String getTextForMessage(int messageId, boolean isIncoming);
+ String getTextForMessage(int messageId, boolean isIncoming, String callingPackage);
- void setLatitudeForMessage(int messageId, boolean isIncoming, double latitude);
+ void setLatitudeForMessage(int messageId, boolean isIncoming, double latitude, String callingPackage);
- double getLatitudeForMessage(int messageId, boolean isIncoming);
+ double getLatitudeForMessage(int messageId, boolean isIncoming, String callingPackage);
- void setLongitudeForMessage(int messageId, boolean isIncoming, double longitude);
+ void setLongitudeForMessage(int messageId, boolean isIncoming, double longitude, String callingPackage);
- double getLongitudeForMessage(int messageId, boolean isIncoming);
+ double getLongitudeForMessage(int messageId, boolean isIncoming, String callingPackage);
// Returns the ID's of the file transfers attached to the given message
- int[] getFileTransfersAttachedToMessage(int messageId, boolean isIncoming);
+ int[] getFileTransfersAttachedToMessage(int messageId, boolean isIncoming, String callingPackage);
- int getSenderParticipant(int messageId);
+ int getSenderParticipant(int messageId, String callingPackage);
/////////////////////////
// RcsOutgoingMessageDelivery APIs
/////////////////////////
// Returns the participant ID's that this message is intended to be delivered to
- int[] getMessageRecipients(int messageId);
+ int[] getMessageRecipients(int messageId, String callingPackage);
- long getOutgoingDeliveryDeliveredTimestamp(int messageId, int participantId);
+ long getOutgoingDeliveryDeliveredTimestamp(int messageId, int participantId, String callingPackage);
- void setOutgoingDeliveryDeliveredTimestamp(int messageId, int participantId, long deliveredTimestamp);
+ void setOutgoingDeliveryDeliveredTimestamp(int messageId, int participantId, long deliveredTimestamp, String callingPackage);
- long getOutgoingDeliverySeenTimestamp(int messageId, int participantId);
+ long getOutgoingDeliverySeenTimestamp(int messageId, int participantId, String callingPackage);
- void setOutgoingDeliverySeenTimestamp(int messageId, int participantId, long seenTimestamp);
+ void setOutgoingDeliverySeenTimestamp(int messageId, int participantId, long seenTimestamp, String callingPackage);
- int getOutgoingDeliveryStatus(int messageId, int participantId);
+ int getOutgoingDeliveryStatus(int messageId, int participantId, String callingPackage);
- void setOutgoingDeliveryStatus(int messageId, int participantId, int status);
+ void setOutgoingDeliveryStatus(int messageId, int participantId, int status, String callingPackage);
/////////////////////////
// RcsFileTransferPart APIs
@@ -203,64 +203,64 @@
// Performs the initial write to storage and returns the row ID.
int storeFileTransfer(int messageId, boolean isIncoming,
- in RcsFileTransferCreationParams fileTransferCreationParams);
+ in RcsFileTransferCreationParams fileTransferCreationParams, String callingPackage);
- void deleteFileTransfer(int partId);
+ void deleteFileTransfer(int partId, String callingPackage);
- void setFileTransferSessionId(int partId, String sessionId);
+ void setFileTransferSessionId(int partId, String sessionId, String callingPackage);
- String getFileTransferSessionId(int partId);
+ String getFileTransferSessionId(int partId, String callingPackage);
- void setFileTransferContentUri(int partId, in Uri contentUri);
+ void setFileTransferContentUri(int partId, in Uri contentUri, String callingPackage);
- Uri getFileTransferContentUri(int partId);
+ Uri getFileTransferContentUri(int partId, String callingPackage);
- void setFileTransferContentType(int partId, String contentType);
+ void setFileTransferContentType(int partId, String contentType, String callingPackage);
- String getFileTransferContentType(int partId);
+ String getFileTransferContentType(int partId, String callingPackage);
- void setFileTransferFileSize(int partId, long fileSize);
+ void setFileTransferFileSize(int partId, long fileSize, String callingPackage);
- long getFileTransferFileSize(int partId);
+ long getFileTransferFileSize(int partId, String callingPackage);
- void setFileTransferTransferOffset(int partId, long transferOffset);
+ void setFileTransferTransferOffset(int partId, long transferOffset, String callingPackage);
- long getFileTransferTransferOffset(int partId);
+ long getFileTransferTransferOffset(int partId, String callingPackage);
- void setFileTransferStatus(int partId, int transferStatus);
+ void setFileTransferStatus(int partId, int transferStatus, String callingPackage);
- int getFileTransferStatus(int partId);
+ int getFileTransferStatus(int partId, String callingPackage);
- void setFileTransferWidth(int partId, int width);
+ void setFileTransferWidth(int partId, int width, String callingPackage);
- int getFileTransferWidth(int partId);
+ int getFileTransferWidth(int partId, String callingPackage);
- void setFileTransferHeight(int partId, int height);
+ void setFileTransferHeight(int partId, int height, String callingPackage);
- int getFileTransferHeight(int partId);
+ int getFileTransferHeight(int partId, String callingPackage);
- void setFileTransferLength(int partId, long length);
+ void setFileTransferLength(int partId, long length, String callingPackage);
- long getFileTransferLength(int partId);
+ long getFileTransferLength(int partId, String callingPackage);
- void setFileTransferPreviewUri(int partId, in Uri uri);
+ void setFileTransferPreviewUri(int partId, in Uri uri, String callingPackage);
- Uri getFileTransferPreviewUri(int partId);
+ Uri getFileTransferPreviewUri(int partId, String callingPackage);
- void setFileTransferPreviewType(int partId, String type);
+ void setFileTransferPreviewType(int partId, String type, String callingPackage);
- String getFileTransferPreviewType(int partId);
+ String getFileTransferPreviewType(int partId, String callingPackage);
/////////////////////////
// RcsEvent APIs
/////////////////////////
- int createGroupThreadNameChangedEvent(long timestamp, int threadId, int originationParticipantId, String newName);
+ int createGroupThreadNameChangedEvent(long timestamp, int threadId, int originationParticipantId, String newName, String callingPackage);
- int createGroupThreadIconChangedEvent(long timestamp, int threadId, int originationParticipantId, in Uri newIcon);
+ int createGroupThreadIconChangedEvent(long timestamp, int threadId, int originationParticipantId, in Uri newIcon, String callingPackage);
- int createGroupThreadParticipantJoinedEvent(long timestamp, int threadId, int originationParticipantId, int participantId);
+ int createGroupThreadParticipantJoinedEvent(long timestamp, int threadId, int originationParticipantId, int participantId, String callingPackage);
- int createGroupThreadParticipantLeftEvent(long timestamp, int threadId, int originationParticipantId, int participantId);
+ int createGroupThreadParticipantLeftEvent(long timestamp, int threadId, int originationParticipantId, int participantId, String callingPackage);
- int createParticipantAliasChangedEvent(long timestamp, int participantId, String newAlias);
+ int createParticipantAliasChangedEvent(long timestamp, int participantId, String newAlias, String callingPackage);
}
\ No newline at end of file
diff --git a/cmds/incidentd/src/cipher/cipher_blocks.proto b/telephony/java/com/android/internal/telephony/IIntegerConsumer.aidl
similarity index 72%
rename from cmds/incidentd/src/cipher/cipher_blocks.proto
rename to telephony/java/com/android/internal/telephony/IIntegerConsumer.aidl
index 5c7ed24..252460e 100644
--- a/cmds/incidentd/src/cipher/cipher_blocks.proto
+++ b/telephony/java/com/android/internal/telephony/IIntegerConsumer.aidl
@@ -14,12 +14,10 @@
* limitations under the License.
*/
-syntax = "proto2";
+package com.android.internal.telephony;
-package android.os.incidentd;
-
-// This proto is never instantiated anywhere. It only exists to keep a record of the format of the
-// encrypted data on disk.
-message CipherBlocks {
- repeated string blocks = 1;
-}
+// Copies consumer pattern for an operation that requires an integer result from another process to
+// finish.
+oneway interface IIntegerConsumer {
+ void accept(int result);
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index f226bb1..68fd9ac 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -18,6 +18,7 @@
import android.app.PendingIntent;
import android.content.Intent;
+import android.content.IntentSender;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Messenger;
@@ -52,6 +53,7 @@
import android.telephony.ims.aidl.IImsRegistrationCallback;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.telephony.CellNetworkScanResult;
+import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.INumberVerificationCallback;
import com.android.internal.telephony.OperatorInfo;
@@ -998,7 +1000,7 @@
/**
* Similar to above, but check for the package whose name is pkgName.
*/
- int checkCarrierPrivilegesForPackage(String pkgName);
+ int checkCarrierPrivilegesForPackage(int subId, String pkgName);
/**
* Similar to above, but check across all phones.
@@ -1051,7 +1053,17 @@
*/
String getLine1AlphaTagForDisplay(int subId, String callingPackage);
- String[] getMergedSubscriberIds(String callingPackage);
+ /**
+ * Return the set of subscriber IDs that should be considered "merged together" for data usage
+ * purposes. This is commonly {@code null} to indicate no merging is required. Any returned
+ * subscribers are sorted in a deterministic order.
+ * <p>
+ * The returned set of subscriber IDs will include the subscriber ID corresponding to this
+ * TelephonyManager's subId.
+ *
+ * @hide
+ */
+ String[] getMergedSubscriberIds(int subId, String callingPackage);
/**
* Override the operator branding for the current ICCID.
@@ -1345,9 +1357,14 @@
in PhoneAccountHandle phoneAccountHandle, boolean enabled);
/**
- * Returns a list of packages that have carrier privileges.
+ * Returns a list of packages that have carrier privileges for the specific phone.
*/
- List<String> getPackagesWithCarrierPrivileges();
+ List<String> getPackagesWithCarrierPrivileges(int phoneId);
+
+ /**
+ * Returns a list of packages that have carrier privileges.
+ */
+ List<String> getPackagesWithCarrierPrivilegesForAllPhones();
/**
* Return the application ID for the app type.
@@ -1970,4 +1987,10 @@
boolean isDataEnabledForApn(int apnType, int subId, String callingPackage);
boolean isApnMetered(int apnType, int subId);
+
+ /**
+ * Enqueue a pending sms Consumer, which will answer with the user specified selection for an
+ * outgoing SmsManager operation.
+ */
+ oneway void enqueueSmsPickResult(String callingPackage, IIntegerConsumer subIdResult);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 0610c5d..f2f3c2d 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -56,38 +56,41 @@
void notifyDataConnection(int state, boolean isDataConnectivityPossible,
String apn, String apnType, in LinkProperties linkProperties,
in NetworkCapabilities networkCapabilities, int networkType, boolean roaming);
- void notifyDataConnectionForSubscriber(int subId, int state, boolean isDataConnectivityPossible,
+ void notifyDataConnectionForSubscriber(int phoneId, int subId, int state,
+ boolean isDataConnectivityPossible,
String apn, String apnType, in LinkProperties linkProperties,
in NetworkCapabilities networkCapabilities, int networkType, boolean roaming);
@UnsupportedAppUsage
void notifyDataConnectionFailed(String apnType);
- void notifyDataConnectionFailedForSubscriber(int subId, String apnType);
+ void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, String apnType);
void notifyCellLocation(in Bundle cellLocation);
void notifyCellLocationForSubscriber(in int subId, in Bundle cellLocation);
- void notifyOtaspChanged(in int otaspMode);
+ void notifyOtaspChanged(in int subId, in int otaspMode);
@UnsupportedAppUsage
void notifyCellInfo(in List<CellInfo> cellInfo);
void notifyPhysicalChannelConfiguration(in List<PhysicalChannelConfig> configs);
void notifyPhysicalChannelConfigurationForSubscriber(in int subId,
in List<PhysicalChannelConfig> configs);
- void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
- int backgroundCallState, int phoneId);
- void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause);
- void notifyPreciseDataConnectionFailed(String apnType, String apn,
+ void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
+ int foregroundCallState, int backgroundCallState);
+ void notifyDisconnectCause(int phoneId, int subId, int disconnectCause,
+ int preciseDisconnectCause);
+ void notifyPreciseDataConnectionFailed(int phoneId, int subId, String apnType, String apn,
int failCause);
void notifyCellInfoForSubscriber(in int subId, in List<CellInfo> cellInfo);
void notifySrvccStateChanged(in int subId, in int lteState);
void notifySimActivationStateChangedForPhoneId(in int phoneId, in int subId,
int activationState, int activationType);
- void notifyOemHookRawEventForSubscriber(in int subId, in byte[] rawData);
+ void notifyOemHookRawEventForSubscriber(in int phoneId, in int subId, in byte[] rawData);
void notifySubscriptionInfoChanged();
void notifyOpportunisticSubscriptionInfoChanged();
void notifyCarrierNetworkChange(in boolean active);
void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state);
void notifyPhoneCapabilityChanged(in PhoneCapability capability);
void notifyActiveDataSubIdChanged(int activeDataSubId);
- void notifyRadioPowerStateChanged(in int state);
- void notifyEmergencyNumberList();
- void notifyCallQualityChanged(in CallQuality callQuality, int phoneId, int callNetworkType);
+ void notifyRadioPowerStateChanged(in int phoneId, in int subId, in int state);
+ void notifyEmergencyNumberList(in int phoneId, in int subId);
+ void notifyCallQualityChanged(in CallQuality callQuality, int phoneId, int subId,
+ int callNetworkType);
void notifyImsDisconnectCause(int subId, in ImsReasonInfo imsReasonInfo);
}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
index e898942..6c311f9 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
@@ -50,9 +50,7 @@
RcsGroupThreadIconChangedEventDescriptor.CREATOR.createFromParcel(parcel);
RcsGroupThreadIconChangedEvent iconChangedEvent =
- iconChangedEventDescriptor.createRcsEvent();
-
-
+ iconChangedEventDescriptor.createRcsEvent(null);
assertThat(iconChangedEvent.getNewIcon()).isEqualTo(newIconUri);
assertThat(iconChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
index 356688d..a60dabb 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
@@ -49,7 +49,7 @@
.createFromParcel(parcel);
RcsGroupThreadNameChangedEvent nameChangedEvent =
- nameChangedEventDescriptor.createRcsEvent();
+ nameChangedEventDescriptor.createRcsEvent(null);
assertThat(nameChangedEvent.getNewName()).isEqualTo(newName);
assertThat(nameChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
index 572fcb8..7b02cb1 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
@@ -48,7 +48,7 @@
.createFromParcel(parcel);
RcsGroupThreadParticipantJoinedEvent participantJoinedEvent =
- participantJoinedEventDescriptor.createRcsEvent();
+ participantJoinedEventDescriptor.createRcsEvent(null);
assertThat(participantJoinedEvent.getJoinedParticipant().getId()).isEqualTo(2);
assertThat(participantJoinedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
index 038b2e8..51466bd 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
@@ -49,7 +49,7 @@
.createFromParcel(parcel);
RcsGroupThreadParticipantLeftEvent participantLeftEvent =
- participantLeftEventDescriptor.createRcsEvent();
+ participantLeftEventDescriptor.createRcsEvent(null);
assertThat(participantLeftEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
assertThat(participantLeftEvent.getLeavingParticipant().getId()).isEqualTo(2);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
index 283c71b..56830df 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
@@ -48,7 +48,7 @@
.createFromParcel(parcel);
RcsParticipantAliasChangedEvent aliasChangedEvent =
- aliasChangedEventDescriptor.createRcsEvent();
+ aliasChangedEventDescriptor.createRcsEvent(null);
assertThat(aliasChangedEvent.getParticipant().getId()).isEqualTo(mParticipantId);
assertThat(aliasChangedEvent.getNewAlias()).isEqualTo(NEW_ALIAS);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
index fb51bda..7a3e384 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
@@ -34,7 +34,7 @@
@Test
public void testCanUnparcel() {
- RcsParticipant rcsParticipant = new RcsParticipant(1);
+ RcsParticipant rcsParticipant = new RcsParticipant(null, 1);
RcsThreadQueryParams rcsThreadQueryParams = new RcsThreadQueryParams.Builder()
.setThreadType(THREAD_TYPE_GROUP)
.setParticipant(rcsParticipant)
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index e556b0a..1932871 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -29,6 +29,14 @@
}
android_test_helper_app {
+ name: "RollbackTestAppAv3",
+ manifest: "TestApp/Av3.xml",
+ sdk_version: "current",
+ srcs: ["TestApp/src/**/*.java"],
+ resource_dirs: ["TestApp/res_v3"],
+}
+
+android_test_helper_app {
name: "RollbackTestAppACrashingV2",
manifest: "TestApp/ACrashingV2.xml",
sdk_version: "current",
@@ -118,6 +126,7 @@
java_resources: [
":RollbackTestAppAv1",
":RollbackTestAppAv2",
+ ":RollbackTestAppAv3",
":RollbackTestAppACrashingV2",
":RollbackTestAppBv1",
":RollbackTestAppBv2",
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index f9304f2..beff0c6 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -35,6 +35,7 @@
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.provider.DeviceConfig;
+import android.provider.Settings;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -60,6 +61,12 @@
private static final String TEST_APP_B = "com.android.tests.rollback.testapp.B";
private static final String INSTRUMENTED_APP = "com.android.tests.rollback";
+ // copied from PackageManagerService#PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS
+ // TODO: find a better place for the property so that it can be imported in tests
+ // maybe android.content.pm.PackageManager?
+ private static final String PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS =
+ "enable_rollback_timeout";
+
/**
* Test basic rollbacks.
*/
@@ -775,6 +782,42 @@
}
}
+ /**
+ * Test failure to enable rollback for multi-package installs.
+ * If any one of the packages fail to enable rollback, we shouldn't enable
+ * rollback for any package.
+ */
+ @Test
+ public void testMultiPackageEnableFail() throws Exception {
+ try {
+ RollbackTestUtils.adoptShellPermissionIdentity(
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.TEST_MANAGE_ROLLBACKS);
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+
+ RollbackTestUtils.uninstall(TEST_APP_A);
+ RollbackTestUtils.uninstall(TEST_APP_B);
+ RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
+
+ // We should fail to enable rollback here because TestApp B is not
+ // already installed.
+ RollbackTestUtils.installMultiPackage(true,
+ "RollbackTestAppAv2.apk",
+ "RollbackTestAppBv2.apk");
+
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
+
+ assertNull(getUniqueRollbackInfoForPackage(
+ rm.getAvailableRollbacks(), TEST_APP_A));
+ assertNull(getUniqueRollbackInfoForPackage(
+ rm.getAvailableRollbacks(), TEST_APP_B));
+ } finally {
+ RollbackTestUtils.dropShellPermissionIdentity();
+ }
+ }
+
@Test
@Ignore("b/120200473")
/**
@@ -871,6 +914,83 @@
}
}
+ /**
+ * Test race between roll back and roll forward.
+ */
+ @Test
+ public void testRollForwardRace() throws Exception {
+ try {
+ RollbackTestUtils.adoptShellPermissionIdentity(
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.TEST_MANAGE_ROLLBACKS,
+ Manifest.permission.MANAGE_ROLLBACKS);
+
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+
+ RollbackTestUtils.uninstall(TEST_APP_A);
+ RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
+ RollbackTestUtils.install("RollbackTestAppAv2.apk", true);
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+ RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+ rm.getAvailableRollbacks(), TEST_APP_A);
+ assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
+
+ // Install a new version of package A, then immediately rollback
+ // the previous version. We expect the rollback to fail, because
+ // it is no longer available.
+ // There are a couple different ways this could fail depending on
+ // thread interleaving, so don't ignore flaky failures.
+ RollbackTestUtils.install("RollbackTestAppAv3.apk", false);
+ try {
+ RollbackTestUtils.rollback(rollback.getRollbackId());
+ // Note: Don't ignore flaky failures here.
+ fail("Expected rollback to fail, but it did not.");
+ } catch (AssertionError e) {
+ Log.i(TAG, "Note expected failure: ", e);
+ // Expected
+ }
+
+ // Note: Don't ignore flaky failures here.
+ assertEquals(3, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+ } finally {
+ RollbackTestUtils.dropShellPermissionIdentity();
+ }
+ }
+
+ @Test
+ public void testEnableRollbackTimeoutFailsRollback() throws Exception {
+ try {
+ RollbackTestUtils.adoptShellPermissionIdentity(
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.TEST_MANAGE_ROLLBACKS,
+ Manifest.permission.MANAGE_ROLLBACKS,
+ Manifest.permission.WRITE_DEVICE_CONFIG);
+
+ //setting the timeout to a very short amount that will definitely be triggered
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+ PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
+ Long.toString(1), false /* makeDefault*/);
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+
+ RollbackTestUtils.uninstall(TEST_APP_A);
+ RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
+ RollbackTestUtils.install("RollbackTestAppAv2.apk", true);
+
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+ assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A));
+ } finally {
+ //setting the timeout back to default
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+ PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
+ null, false /* makeDefault*/);
+ RollbackTestUtils.dropShellPermissionIdentity();
+ }
+ }
+
// Helper function to test that the given rollback info is a rollback for
// the atomic set {A2, B2} -> {A1, B1}.
private void assertRollbackInfoForAandB(RollbackInfo rollback) {
diff --git a/tests/RollbackTest/TestApp/Av3.xml b/tests/RollbackTest/TestApp/Av3.xml
new file mode 100644
index 0000000..9725c9f7
--- /dev/null
+++ b/tests/RollbackTest/TestApp/Av3.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.rollback.testapp.A"
+ android:versionCode="3"
+ android:versionName="3.0" >
+
+
+ <uses-sdk android:minSdkVersion="19" />
+
+ <application android:label="Rollback Test App A v3">
+ <receiver android:name="com.android.tests.rollback.testapp.ProcessUserData"
+ android:exported="true" />
+ <activity android:name="com.android.tests.rollback.testapp.MainActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/RollbackTest/TestApp/res_v3/values-anydpi/values.xml b/tests/RollbackTest/TestApp/res_v3/values-anydpi/values.xml
new file mode 100644
index 0000000..f2d8992
--- /dev/null
+++ b/tests/RollbackTest/TestApp/res_v3/values-anydpi/values.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open 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>
+ <integer name="split_version">3</integer>
+</resources>
diff --git a/tests/RollbackTest/TestApp/res_v3/values/values.xml b/tests/RollbackTest/TestApp/res_v3/values/values.xml
new file mode 100644
index 0000000..968168a
--- /dev/null
+++ b/tests/RollbackTest/TestApp/res_v3/values/values.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open 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>
+ <integer name="app_version">3</integer>
+ <integer name="split_version">0</integer>
+</resources>
diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp
index 3b2e34a..07525a6 100644
--- a/tests/net/common/Android.bp
+++ b/tests/net/common/Android.bp
@@ -23,6 +23,7 @@
"androidx.test.rules",
"frameworks-net-testutils",
"junit",
+ "mockito-target-minus-junit4",
],
libs: [
"android.test.base.stubs",
diff --git a/tests/net/common/java/android/net/CaptivePortalTest.java b/tests/net/common/java/android/net/CaptivePortalTest.java
new file mode 100644
index 0000000..eed7159f
--- /dev/null
+++ b/tests/net/common/java/android/net/CaptivePortalTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.RemoteException;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CaptivePortalTest {
+ private static final int DEFAULT_TIMEOUT_MS = 5000;
+ private static final String TEST_PACKAGE_NAME = "com.google.android.test";
+
+ private final class MyCaptivePortalImpl extends ICaptivePortal.Stub {
+ int mCode = -1;
+ String mPackageName = null;
+
+ @Override
+ public void appResponse(final int response) throws RemoteException {
+ mCode = response;
+ }
+
+ @Override
+ public void logEvent(int eventId, String packageName) throws RemoteException {
+ mCode = eventId;
+ mPackageName = packageName;
+ }
+ }
+
+ private interface TestFunctor {
+ void useCaptivePortal(CaptivePortal o);
+ }
+
+ private MyCaptivePortalImpl runCaptivePortalTest(TestFunctor f) {
+ final MyCaptivePortalImpl cp = new MyCaptivePortalImpl();
+ f.useCaptivePortal(new CaptivePortal(cp.asBinder()));
+ return cp;
+ }
+
+ @Test
+ public void testReportCaptivePortalDismissed() {
+ final MyCaptivePortalImpl result =
+ runCaptivePortalTest(c -> c.reportCaptivePortalDismissed());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_DISMISSED);
+ }
+
+ @Test
+ public void testIgnoreNetwork() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.ignoreNetwork());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_UNWANTED);
+ }
+
+ @Test
+ public void testUseNetwork() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.useNetwork());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_WANTED_AS_IS);
+ }
+
+ @Test
+ public void testLogEvent() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.logEvent(
+ MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY,
+ TEST_PACKAGE_NAME));
+ assertEquals(result.mCode, MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY);
+ assertEquals(result.mPackageName, TEST_PACKAGE_NAME);
+ }
+}
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index 709f5f6..e1c4238 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -46,28 +47,80 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class LinkPropertiesTest {
- private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1");
- private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress(
+ private static final InetAddress ADDRV4 = InetAddresses.parseNumericAddress("75.208.6.1");
+ private static final InetAddress ADDRV6 = InetAddresses.parseNumericAddress(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334");
- private static InetAddress DNS1 = NetworkUtils.numericToInetAddress("75.208.7.1");
- private static InetAddress DNS2 = NetworkUtils.numericToInetAddress("69.78.7.1");
- private static InetAddress DNS6 = NetworkUtils.numericToInetAddress("2001:4860:4860::8888");
- private static InetAddress PCSCFV6 = NetworkUtils.numericToInetAddress(
+ private static final InetAddress DNS1 = InetAddresses.parseNumericAddress("75.208.7.1");
+ private static final InetAddress DNS2 = InetAddresses.parseNumericAddress("69.78.7.1");
+ private static final InetAddress DNS6 = InetAddresses.parseNumericAddress(
+ "2001:4860:4860::8888");
+ private static final InetAddress PRIVDNS1 = InetAddresses.parseNumericAddress("1.1.1.1");
+ private static final InetAddress PRIVDNS2 = InetAddresses.parseNumericAddress("1.0.0.1");
+ private static final InetAddress PRIVDNS6 = InetAddresses.parseNumericAddress(
+ "2606:4700:4700::1111");
+ private static final InetAddress PCSCFV4 = InetAddresses.parseNumericAddress("10.77.25.37");
+ private static final InetAddress PCSCFV6 = InetAddresses.parseNumericAddress(
"2001:0db8:85a3:0000:0000:8a2e:0370:1");
- private static InetAddress GATEWAY1 = NetworkUtils.numericToInetAddress("75.208.8.1");
- private static InetAddress GATEWAY2 = NetworkUtils.numericToInetAddress("69.78.8.1");
- private static InetAddress GATEWAY61 = NetworkUtils.numericToInetAddress("fe80::6:0000:613");
- private static InetAddress GATEWAY62 = NetworkUtils.numericToInetAddress("fe80::6:2222");
- private static String NAME = "qmi0";
- private static int MTU = 1500;
-
- private static LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32);
- private static LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
- private static LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
+ private static final InetAddress GATEWAY1 = InetAddresses.parseNumericAddress("75.208.8.1");
+ private static final InetAddress GATEWAY2 = InetAddresses.parseNumericAddress("69.78.8.1");
+ private static final InetAddress GATEWAY61 = InetAddresses.parseNumericAddress(
+ "fe80::6:0000:613");
+ private static final InetAddress GATEWAY62 = InetAddresses.parseNumericAddress("fe80::6:2222");
+ private static final String NAME = "qmi0";
+ private static final String DOMAINS = "google.com";
+ private static final String PRIV_DNS_SERVER_NAME = "private.dns.com";
+ private static final String TCP_BUFFER_SIZES = "524288,1048576,2097152,262144,524288,1048576";
+ private static final int MTU = 1500;
+ private static final LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32);
+ private static final LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
+ private static final LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
// TODO: replace all calls to NetworkUtils.numericToInetAddress with calls to this method.
private InetAddress Address(String addrString) {
- return NetworkUtils.numericToInetAddress(addrString);
+ return InetAddresses.parseNumericAddress(addrString);
+ }
+
+ private void checkEmpty(final LinkProperties lp) {
+ assertEquals(0, lp.getAllInterfaceNames().size());
+ assertEquals(0, lp.getAllAddresses().size());
+ assertEquals(0, lp.getDnsServers().size());
+ assertEquals(0, lp.getValidatedPrivateDnsServers().size());
+ assertEquals(0, lp.getPcscfServers().size());
+ assertEquals(0, lp.getAllRoutes().size());
+ assertEquals(0, lp.getAllLinkAddresses().size());
+ assertEquals(0, lp.getStackedLinks().size());
+ assertEquals(0, lp.getMtu());
+ assertNull(lp.getPrivateDnsServerName());
+ assertNull(lp.getDomains());
+ assertNull(lp.getHttpProxy());
+ assertNull(lp.getTcpBufferSizes());
+ assertNull(lp.getNat64Prefix());
+ assertFalse(lp.isProvisioned());
+ assertFalse(lp.isIpv4Provisioned());
+ assertFalse(lp.isIpv6Provisioned());
+ assertFalse(lp.isPrivateDnsActive());
+ }
+
+ private LinkProperties makeTestObject() {
+ final LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName(NAME);
+ lp.addLinkAddress(LINKADDRV4);
+ lp.addLinkAddress(LINKADDRV6);
+ lp.addDnsServer(DNS1);
+ lp.addDnsServer(DNS2);
+ lp.addValidatedPrivateDnsServer(PRIVDNS1);
+ lp.addValidatedPrivateDnsServer(PRIVDNS2);
+ lp.setUsePrivateDns(true);
+ lp.setPrivateDnsServerName(PRIV_DNS_SERVER_NAME);
+ lp.addPcscfServer(PCSCFV6);
+ lp.setDomains(DOMAINS);
+ lp.addRoute(new RouteInfo(GATEWAY1));
+ lp.addRoute(new RouteInfo(GATEWAY2));
+ lp.setHttpProxy(ProxyInfo.buildDirectProxy("test", 8888));
+ lp.setMtu(MTU);
+ lp.setTcpBufferSizes(TCP_BUFFER_SIZES);
+ lp.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96"));
+ return lp;
}
public void assertLinkPropertiesEqual(LinkProperties source, LinkProperties target) {
@@ -170,8 +223,7 @@
target.clear();
target.setInterfaceName(NAME);
// change link addresses
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress("75.208.6.2"), 32));
+ target.addLinkAddress(new LinkAddress(Address("75.208.6.2"), 32));
target.addLinkAddress(LINKADDRV6);
target.addDnsServer(DNS1);
target.addDnsServer(DNS2);
@@ -186,7 +238,7 @@
target.addLinkAddress(LINKADDRV4);
target.addLinkAddress(LINKADDRV6);
// change dnses
- target.addDnsServer(NetworkUtils.numericToInetAddress("75.208.7.2"));
+ target.addDnsServer(Address("75.208.7.2"));
target.addDnsServer(DNS2);
target.addPcscfServer(PCSCFV6);
target.addRoute(new RouteInfo(GATEWAY1));
@@ -198,11 +250,10 @@
target.setInterfaceName(NAME);
target.addLinkAddress(LINKADDRV4);
target.addLinkAddress(LINKADDRV6);
- target.addDnsServer(NetworkUtils.numericToInetAddress("75.208.7.2"));
+ target.addDnsServer(Address("75.208.7.2"));
target.addDnsServer(DNS2);
// change pcscf
- target.addPcscfServer(NetworkUtils.numericToInetAddress(
- "2001::1"));
+ target.addPcscfServer(Address("2001::1"));
target.addRoute(new RouteInfo(GATEWAY1));
target.addRoute(new RouteInfo(GATEWAY2));
target.setMtu(MTU);
@@ -215,7 +266,7 @@
target.addDnsServer(DNS1);
target.addDnsServer(DNS2);
// change gateway
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
+ target.addRoute(new RouteInfo(Address("75.208.8.2")));
target.addRoute(new RouteInfo(GATEWAY2));
target.setMtu(MTU);
assertFalse(source.equals(target));
@@ -285,10 +336,15 @@
}
}
+ private void assertAllRoutesNotHaveInterface(String iface, LinkProperties lp) {
+ for (RouteInfo r : lp.getRoutes()) {
+ assertNotEquals(iface, r.getInterface());
+ }
+ }
+
@Test
public void testRouteInterfaces() {
- LinkAddress prefix = new LinkAddress(
- NetworkUtils.numericToInetAddress("2001:db8::"), 32);
+ LinkAddress prefix = new LinkAddress(Address("2001:db8::"), 32);
InetAddress address = ADDRV6;
// Add a route with no interface to a LinkProperties with no interface. No errors.
@@ -312,6 +368,8 @@
// Change the interface name. All the routes should change their interface name too.
lp.setInterfaceName("rmnet0");
assertAllRoutesHaveInterface("rmnet0", lp);
+ assertAllRoutesNotHaveInterface(null, lp);
+ assertAllRoutesNotHaveInterface("wlan0", lp);
// Now add a route with the wrong interface. This causes an exception too.
try {
@@ -325,6 +383,7 @@
lp.addRoute(r);
assertEquals(2, lp.getRoutes().size());
assertAllRoutesHaveInterface("wlan0", lp);
+ assertAllRoutesNotHaveInterface("rmnet0", lp);
// Routes with null interfaces are converted to wlan0.
r = RouteInfo.makeHostRoute(ADDRV6, null);
@@ -334,14 +393,23 @@
// Check comparisons work.
LinkProperties lp2 = new LinkProperties(lp);
- assertAllRoutesHaveInterface("wlan0", lp);
+ assertAllRoutesHaveInterface("wlan0", lp2);
assertEquals(0, lp.compareAllRoutes(lp2).added.size());
assertEquals(0, lp.compareAllRoutes(lp2).removed.size());
lp2.setInterfaceName("p2p0");
assertAllRoutesHaveInterface("p2p0", lp2);
+ assertAllRoutesNotHaveInterface("wlan0", lp2);
assertEquals(3, lp.compareAllRoutes(lp2).added.size());
assertEquals(3, lp.compareAllRoutes(lp2).removed.size());
+
+ // Check remove works
+ lp.removeRoute(new RouteInfo(prefix, address, null));
+ assertEquals(3, lp.getRoutes().size());
+ lp.removeRoute(new RouteInfo(prefix, address, "wlan0"));
+ assertEquals(2, lp.getRoutes().size());
+ assertAllRoutesHaveInterface("wlan0", lp);
+ assertAllRoutesNotHaveInterface("p2p0", lp);
}
@Test
@@ -488,18 +556,26 @@
}
@Test
- public void testSetLinkAddresses() {
- LinkProperties lp = new LinkProperties();
+ public void testLinkAddresses() {
+ final LinkProperties lp = new LinkProperties();
lp.addLinkAddress(LINKADDRV4);
lp.addLinkAddress(LINKADDRV6);
- LinkProperties lp2 = new LinkProperties();
+ final LinkProperties lp2 = new LinkProperties();
lp2.addLinkAddress(LINKADDRV6);
- assertFalse(lp.equals(lp2));
+ final LinkProperties lp3 = new LinkProperties();
+ final List<LinkAddress> linkAddresses = Arrays.asList(LINKADDRV4);
+ lp3.setLinkAddresses(linkAddresses);
- lp2.setLinkAddresses(lp.getLinkAddresses());
- assertTrue(lp.equals(lp));
+ assertFalse(lp.equals(lp2));
+ assertFalse(lp2.equals(lp3));
+
+ lp.removeLinkAddress(LINKADDRV4);
+ assertTrue(lp.equals(lp2));
+
+ lp2.setLinkAddresses(lp3.getLinkAddresses());
+ assertTrue(lp2.equals(lp3));
}
@Test
@@ -675,9 +751,9 @@
assertTrue(v4lp.isReachable(DNS2));
final LinkProperties v6lp = new LinkProperties();
- final InetAddress kLinkLocalDns = NetworkUtils.numericToInetAddress("fe80::6:1");
- final InetAddress kLinkLocalDnsWithScope = NetworkUtils.numericToInetAddress("fe80::6:2%43");
- final InetAddress kOnLinkDns = NetworkUtils.numericToInetAddress("2001:db8:85a3::53");
+ final InetAddress kLinkLocalDns = Address("fe80::6:1");
+ final InetAddress kLinkLocalDnsWithScope = Address("fe80::6:2%43");
+ final InetAddress kOnLinkDns = Address("2001:db8:85a3::53");
assertFalse(v6lp.isReachable(kLinkLocalDns));
assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope));
assertFalse(v6lp.isReachable(kOnLinkDns));
@@ -686,8 +762,7 @@
// Add a link-local route, making the link-local DNS servers reachable. Because
// we assume the presence of an IPv6 link-local address, link-local DNS servers
// are considered reachable, but only those with a non-zero scope identifier.
- assertTrue(v6lp.addRoute(new RouteInfo(
- new IpPrefix(NetworkUtils.numericToInetAddress("fe80::"), 64))));
+ assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(Address("fe80::"), 64))));
assertFalse(v6lp.isReachable(kLinkLocalDns));
assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
assertFalse(v6lp.isReachable(kOnLinkDns));
@@ -703,8 +778,7 @@
// Add a global route on link, but no global address yet. DNS servers reachable
// via a route that doesn't require a gateway: give them the benefit of the
// doubt and hope the link-local source address suffices for communication.
- assertTrue(v6lp.addRoute(new RouteInfo(
- new IpPrefix(NetworkUtils.numericToInetAddress("2001:db8:85a3::"), 64))));
+ assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(Address("2001:db8:85a3::"), 64))));
assertFalse(v6lp.isReachable(kLinkLocalDns));
assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
assertTrue(v6lp.isReachable(kOnLinkDns));
@@ -766,8 +840,8 @@
LinkProperties rmnet1 = new LinkProperties();
rmnet1.setInterfaceName("rmnet1");
rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8"));
- RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null,
- NetworkUtils.numericToInetAddress("10.0.0.1"), rmnet1.getInterfaceName());
+ RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, Address("10.0.0.1"),
+ rmnet1.getInterfaceName());
RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
rmnet1.getInterfaceName());
rmnet1.addRoute(defaultRoute1);
@@ -785,8 +859,8 @@
rmnet2.setInterfaceName("rmnet2");
rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64"));
rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64"));
- RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null,
- NetworkUtils.numericToInetAddress("2001:db8::1"), rmnet2.getInterfaceName());
+ RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, Address("2001:db8::1"),
+ rmnet2.getInterfaceName());
RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null,
rmnet2.getInterfaceName());
RouteInfo linkLocalRoute2 = new RouteInfo(new IpPrefix("fe80::/64"), null,
@@ -876,4 +950,111 @@
LinkProperties empty = new LinkProperties();
TestUtils.assertParcelingIsLossless(empty);
}
+
+ @Test
+ public void testConstructor() {
+ LinkProperties lp = new LinkProperties();
+ checkEmpty(lp);
+ assertLinkPropertiesEqual(lp, new LinkProperties(lp));
+ assertLinkPropertiesEqual(lp, new LinkProperties());
+
+ lp = makeTestObject();
+ assertLinkPropertiesEqual(lp, new LinkProperties(lp));
+ }
+
+ @Test
+ public void testDnsServers() {
+ final LinkProperties lp = new LinkProperties();
+ final List<InetAddress> dnsServers = Arrays.asList(DNS1, DNS2);
+ lp.setDnsServers(dnsServers);
+ assertEquals(2, lp.getDnsServers().size());
+ assertEquals(DNS1, lp.getDnsServers().get(0));
+ assertEquals(DNS2, lp.getDnsServers().get(1));
+
+ lp.removeDnsServer(DNS1);
+ assertEquals(1, lp.getDnsServers().size());
+ assertEquals(DNS2, lp.getDnsServers().get(0));
+
+ lp.addDnsServer(DNS6);
+ assertEquals(2, lp.getDnsServers().size());
+ assertEquals(DNS2, lp.getDnsServers().get(0));
+ assertEquals(DNS6, lp.getDnsServers().get(1));
+ }
+
+ @Test
+ public void testValidatedPrivateDnsServers() {
+ final LinkProperties lp = new LinkProperties();
+ final List<InetAddress> privDnsServers = Arrays.asList(PRIVDNS1, PRIVDNS2);
+ lp.setValidatedPrivateDnsServers(privDnsServers);
+ assertEquals(2, lp.getValidatedPrivateDnsServers().size());
+ assertEquals(PRIVDNS1, lp.getValidatedPrivateDnsServers().get(0));
+ assertEquals(PRIVDNS2, lp.getValidatedPrivateDnsServers().get(1));
+
+ lp.removeValidatedPrivateDnsServer(PRIVDNS1);
+ assertEquals(1, lp.getValidatedPrivateDnsServers().size());
+ assertEquals(PRIVDNS2, lp.getValidatedPrivateDnsServers().get(0));
+
+ lp.addValidatedPrivateDnsServer(PRIVDNS6);
+ assertEquals(2, lp.getValidatedPrivateDnsServers().size());
+ assertEquals(PRIVDNS2, lp.getValidatedPrivateDnsServers().get(0));
+ assertEquals(PRIVDNS6, lp.getValidatedPrivateDnsServers().get(1));
+ }
+
+ @Test
+ public void testPcscfServers() {
+ final LinkProperties lp = new LinkProperties();
+ final List<InetAddress> pcscfServers = Arrays.asList(PCSCFV4);
+ lp.setPcscfServers(pcscfServers);
+ assertEquals(1, lp.getPcscfServers().size());
+ assertEquals(PCSCFV4, lp.getPcscfServers().get(0));
+
+ lp.removePcscfServer(PCSCFV4);
+ assertEquals(0, lp.getPcscfServers().size());
+
+ lp.addPcscfServer(PCSCFV6);
+ assertEquals(1, lp.getPcscfServers().size());
+ assertEquals(PCSCFV6, lp.getPcscfServers().get(0));
+ }
+
+ @Test
+ public void testTcpBufferSizes() {
+ final LinkProperties lp = makeTestObject();
+ assertEquals(TCP_BUFFER_SIZES, lp.getTcpBufferSizes());
+
+ lp.setTcpBufferSizes(null);
+ assertNull(lp.getTcpBufferSizes());
+ }
+
+ @Test
+ public void testHasIpv6DefaultRoute() {
+ final LinkProperties lp = makeTestObject();
+ assertFalse(lp.hasIPv6DefaultRoute());
+
+ lp.addRoute(new RouteInfo(GATEWAY61));
+ assertTrue(lp.hasIPv6DefaultRoute());
+ }
+
+ @Test
+ public void testHttpProxy() {
+ final LinkProperties lp = makeTestObject();
+ assertTrue(lp.getHttpProxy().equals(ProxyInfo.buildDirectProxy("test", 8888)));
+ }
+
+ @Test
+ public void testPrivateDnsServerName() {
+ final LinkProperties lp = makeTestObject();
+ assertEquals(PRIV_DNS_SERVER_NAME, lp.getPrivateDnsServerName());
+
+ lp.setPrivateDnsServerName(null);
+ assertNull(lp.getPrivateDnsServerName());
+ }
+
+ @Test
+ public void testUsePrivateDns() {
+ final LinkProperties lp = makeTestObject();
+ assertTrue(lp.isPrivateDnsActive());
+
+ lp.clear();
+ assertFalse(lp.isPrivateDnsActive());
+ }
}
diff --git a/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java
index 3ed8a86..0ce7c91 100644
--- a/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java
@@ -17,7 +17,9 @@
package android.net.apf;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -32,8 +34,12 @@
@SmallTest
public class ApfCapabilitiesTest {
@Test
- public void testParcelUnparcel() {
+ public void testConstructAndParcel() {
final ApfCapabilities caps = new ApfCapabilities(123, 456, 789);
+ assertEquals(123, caps.apfVersionSupported);
+ assertEquals(456, caps.maximumApfProgramSize);
+ assertEquals(789, caps.apfPacketFormat);
+
ParcelableTestUtil.assertFieldCountEquals(3, ApfCapabilities.class);
TestUtils.assertParcelingIsLossless(caps);
@@ -46,4 +52,14 @@
assertNotEquals(new ApfCapabilities(1, 3, 3), new ApfCapabilities(1, 2, 3));
assertNotEquals(new ApfCapabilities(1, 2, 4), new ApfCapabilities(1, 2, 3));
}
+
+ @Test
+ public void testHasDataAccess() {
+ //hasDataAccess is only supported starting at apf version 4.
+ ApfCapabilities caps = new ApfCapabilities(1 /* apfVersionSupported */, 2, 3);
+ assertFalse(caps.hasDataAccess());
+
+ caps = new ApfCapabilities(4 /* apfVersionSupported */, 5, 6);
+ assertTrue(caps.hasDataAccess());
+ }
}
diff --git a/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt b/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt
new file mode 100644
index 0000000..8d055c9
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ApfProgramEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ private infix fun Int.hasFlag(flag: Int) = (this and (1 shl flag)) != 0
+
+ @Test
+ fun testBuilderAndParcel() {
+ val apfProgramEvent = ApfProgramEvent.Builder()
+ .setLifetime(1)
+ .setActualLifetime(2)
+ .setFilteredRas(3)
+ .setCurrentRas(4)
+ .setProgramLength(5)
+ .setFlags(true, true)
+ .build()
+
+ assertEquals(1, apfProgramEvent.lifetime)
+ assertEquals(2, apfProgramEvent.actualLifetime)
+ assertEquals(3, apfProgramEvent.filteredRas)
+ assertEquals(4, apfProgramEvent.currentRas)
+ assertEquals(5, apfProgramEvent.programLength)
+ assertEquals(ApfProgramEvent.flagsFor(true, true), apfProgramEvent.flags)
+
+ testParcel(apfProgramEvent, 6)
+ }
+
+ @Test
+ fun testFlagsFor() {
+ var flags = ApfProgramEvent.flagsFor(false, false)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(true, false)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(false, true)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(true, true)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/ApfStatsTest.kt b/tests/net/common/java/android/net/metrics/ApfStatsTest.kt
new file mode 100644
index 0000000..f8eb40c
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ApfStatsTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ApfStatsTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testBuilderAndParcel() {
+ val apfStats = ApfStats.Builder()
+ .setDurationMs(Long.MAX_VALUE)
+ .setReceivedRas(1)
+ .setMatchingRas(2)
+ .setDroppedRas(3)
+ .setZeroLifetimeRas(4)
+ .setParseErrors(5)
+ .setProgramUpdates(6)
+ .setProgramUpdatesAll(7)
+ .setProgramUpdatesAllowingMulticast(8)
+ .setMaxProgramSize(9)
+ .build()
+
+ assertEquals(Long.MAX_VALUE, apfStats.durationMs)
+ assertEquals(1, apfStats.receivedRas)
+ assertEquals(2, apfStats.matchingRas)
+ assertEquals(3, apfStats.droppedRas)
+ assertEquals(4, apfStats.zeroLifetimeRas)
+ assertEquals(5, apfStats.parseErrors)
+ assertEquals(6, apfStats.programUpdates)
+ assertEquals(7, apfStats.programUpdatesAll)
+ assertEquals(8, apfStats.programUpdatesAllowingMulticast)
+ assertEquals(9, apfStats.maxProgramSize)
+
+ testParcel(apfStats, 10)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt b/tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt
new file mode 100644
index 0000000..36e9f8c
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val FAKE_MESSAGE = "test"
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class DhcpClientEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testBuilderAndParcel() {
+ val dhcpClientEvent = DhcpClientEvent.Builder()
+ .setMsg(FAKE_MESSAGE)
+ .setDurationMs(Integer.MAX_VALUE)
+ .build()
+
+ assertEquals(FAKE_MESSAGE, dhcpClientEvent.msg)
+ assertEquals(Integer.MAX_VALUE, dhcpClientEvent.durationMs)
+
+ testParcel(dhcpClientEvent, 2)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt b/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt
index e191953..e9d5e6d 100644
--- a/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt
+++ b/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt
@@ -13,9 +13,7 @@
import org.junit.runner.RunWith
private const val TEST_ERROR_CODE = 12345
-/**
- * DHCP Optional Type: DHCP Subnet Mask (Copy from DhcpPacket.java)
- */
+//DHCP Optional Type: DHCP Subnet Mask (Copy from DhcpPacket.java due to it's protected)
private const val DHCP_SUBNET_MASK = 1
@RunWith(AndroidJUnit4::class)
diff --git a/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java b/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java
new file mode 100644
index 0000000..d4780d3
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import android.net.ConnectivityMetricsEvent;
+import android.net.IIpConnectivityMetrics;
+import android.net.Network;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.BitUtils;
+
+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 java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpConnectivityLogTest {
+ private static final int FAKE_NET_ID = 100;
+ private static final int[] FAKE_TRANSPORT_TYPES = BitUtils.unpackBits(TRANSPORT_WIFI);
+ private static final long FAKE_TIME_STAMP = System.currentTimeMillis();
+ private static final String FAKE_INTERFACE_NAME = "test";
+ private static final IpReachabilityEvent FAKE_EV =
+ new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
+
+ @Mock IIpConnectivityMetrics mMockService;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testLoggingEvents() throws Exception {
+ IpConnectivityLog logger = new IpConnectivityLog(mMockService);
+
+ assertTrue(logger.log(FAKE_EV));
+ assertTrue(logger.log(FAKE_TIME_STAMP, FAKE_EV));
+ assertTrue(logger.log(FAKE_NET_ID, FAKE_TRANSPORT_TYPES, FAKE_EV));
+ assertTrue(logger.log(new Network(FAKE_NET_ID), FAKE_TRANSPORT_TYPES, FAKE_EV));
+ assertTrue(logger.log(FAKE_INTERFACE_NAME, FAKE_EV));
+ assertTrue(logger.log(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID, TRANSPORT_WIFI,
+ FAKE_INTERFACE_NAME)));
+
+ List<ConnectivityMetricsEvent> got = verifyEvents(6);
+ assertEventsEqual(makeExpectedEvent(got.get(0).timestamp, 0, 0, null), got.get(0));
+ assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, 0, 0, null), got.get(1));
+ assertEventsEqual(makeExpectedEvent(got.get(2).timestamp, FAKE_NET_ID,
+ TRANSPORT_WIFI, null), got.get(2));
+ assertEventsEqual(makeExpectedEvent(got.get(3).timestamp, FAKE_NET_ID,
+ TRANSPORT_WIFI, null), got.get(3));
+ assertEventsEqual(makeExpectedEvent(got.get(4).timestamp, 0, 0, FAKE_INTERFACE_NAME),
+ got.get(4));
+ assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID,
+ TRANSPORT_WIFI, FAKE_INTERFACE_NAME), got.get(5));
+ }
+
+ @Test
+ public void testLoggingEventsWithMultipleCallers() throws Exception {
+ IpConnectivityLog logger = new IpConnectivityLog(mMockService);
+
+ final int nCallers = 10;
+ final int nEvents = 10;
+ for (int n = 0; n < nCallers; n++) {
+ final int i = n;
+ new Thread() {
+ public void run() {
+ for (int j = 0; j < nEvents; j++) {
+ assertTrue(logger.log(makeExpectedEvent(
+ FAKE_TIME_STAMP + i * 100 + j,
+ FAKE_NET_ID + i * 100 + j,
+ ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR,
+ FAKE_INTERFACE_NAME)));
+ }
+ }
+ }.start();
+ }
+
+ List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
+ Collections.sort(got, EVENT_COMPARATOR);
+ Iterator<ConnectivityMetricsEvent> iter = got.iterator();
+ for (int i = 0; i < nCallers; i++) {
+ for (int j = 0; j < nEvents; j++) {
+ final long expectedTimestamp = FAKE_TIME_STAMP + i * 100 + j;
+ final int expectedNetId = FAKE_NET_ID + i * 100 + j;
+ final long expectedTransports =
+ ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR;
+ assertEventsEqual(makeExpectedEvent(expectedTimestamp, expectedNetId,
+ expectedTransports, FAKE_INTERFACE_NAME), iter.next());
+ }
+ }
+ }
+
+ private List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
+ ArgumentCaptor<ConnectivityMetricsEvent> captor =
+ ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
+ verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
+ return captor.getAllValues();
+ }
+
+ private List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
+ return verifyEvents(n, 10);
+ }
+
+
+ private ConnectivityMetricsEvent makeExpectedEvent(long timestamp, int netId, long transports,
+ String ifname) {
+ ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
+ ev.timestamp = timestamp;
+ ev.data = FAKE_EV;
+ ev.netId = netId;
+ ev.transports = transports;
+ ev.ifname = ifname;
+ return ev;
+ }
+
+ /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
+ private void assertEventsEqual(ConnectivityMetricsEvent expected,
+ ConnectivityMetricsEvent got) {
+ assertEquals(expected.data, got.data);
+ assertEquals(expected.timestamp, got.timestamp);
+ assertEquals(expected.netId, got.netId);
+ assertEquals(expected.transports, got.transports);
+ assertEquals(expected.ifname, got.ifname);
+ }
+
+ static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
+ Comparator.comparingLong((ev) -> ev.timestamp);
+}
diff --git a/tests/net/common/java/android/net/metrics/IpManagerEventTest.kt b/tests/net/common/java/android/net/metrics/IpManagerEventTest.kt
new file mode 100644
index 0000000..5144ca5
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/IpManagerEventTest.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class IpManagerEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ (IpManagerEvent.PROVISIONING_OK..IpManagerEvent.ERROR_INTERFACE_NOT_FOUND).forEach {
+ val ipManagerEvent = IpManagerEvent(it, Long.MAX_VALUE)
+ assertEquals(it, ipManagerEvent.eventType)
+ assertEquals(Long.MAX_VALUE, ipManagerEvent.durationMs)
+
+ testParcel(ipManagerEvent, 2)
+ }
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt b/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt
new file mode 100644
index 0000000..d76ebf6
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class IpReachabilityEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ (IpReachabilityEvent.PROBE..IpReachabilityEvent.PROVISIONING_LOST_ORGANIC).forEach {
+ val ipReachabilityEvent = IpReachabilityEvent(it)
+ assertEquals(it, ipReachabilityEvent.eventType)
+
+ testParcel(ipReachabilityEvent, 1)
+ }
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/NetworkEventTest.kt b/tests/net/common/java/android/net/metrics/NetworkEventTest.kt
new file mode 100644
index 0000000..8b52e81
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/NetworkEventTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class NetworkEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ (NetworkEvent.NETWORK_CONNECTED..NetworkEvent.NETWORK_PARTIAL_CONNECTIVITY).forEach {
+ var networkEvent = NetworkEvent(it)
+ assertEquals(it, networkEvent.eventType)
+ assertEquals(0, networkEvent.durationMs)
+
+ networkEvent = NetworkEvent(it, Long.MAX_VALUE)
+ assertEquals(it, networkEvent.eventType)
+ assertEquals(Long.MAX_VALUE, networkEvent.durationMs)
+
+ testParcel(networkEvent, 2)
+ }
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/RaEventTest.kt b/tests/net/common/java/android/net/metrics/RaEventTest.kt
new file mode 100644
index 0000000..f38d328
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/RaEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val NO_LIFETIME: Long = -1L
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class RaEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ var raEvent = RaEvent.Builder().build()
+ assertEquals(NO_LIFETIME, raEvent.routerLifetime)
+ assertEquals(NO_LIFETIME, raEvent.prefixValidLifetime)
+ assertEquals(NO_LIFETIME, raEvent.prefixPreferredLifetime)
+ assertEquals(NO_LIFETIME, raEvent.routeInfoLifetime)
+ assertEquals(NO_LIFETIME, raEvent.rdnssLifetime)
+ assertEquals(NO_LIFETIME, raEvent.dnsslLifetime)
+
+ raEvent = RaEvent.Builder()
+ .updateRouterLifetime(1)
+ .updatePrefixValidLifetime(2)
+ .updatePrefixPreferredLifetime(3)
+ .updateRouteInfoLifetime(4)
+ .updateRdnssLifetime(5)
+ .updateDnsslLifetime(6)
+ .build()
+ assertEquals(1, raEvent.routerLifetime)
+ assertEquals(2, raEvent.prefixValidLifetime)
+ assertEquals(3, raEvent.prefixPreferredLifetime)
+ assertEquals(4, raEvent.routeInfoLifetime)
+ assertEquals(5, raEvent.rdnssLifetime)
+ assertEquals(6, raEvent.dnsslLifetime)
+
+ raEvent = RaEvent.Builder()
+ .updateRouterLifetime(Long.MIN_VALUE)
+ .updateRouterLifetime(Long.MAX_VALUE)
+ .build()
+ assertEquals(Long.MIN_VALUE, raEvent.routerLifetime)
+
+ raEvent = RaEvent(1, 2, 3, 4, 5, 6)
+ assertEquals(1, raEvent.routerLifetime)
+ assertEquals(2, raEvent.prefixValidLifetime)
+ assertEquals(3, raEvent.prefixPreferredLifetime)
+ assertEquals(4, raEvent.routeInfoLifetime)
+ assertEquals(5, raEvent.rdnssLifetime)
+ assertEquals(6, raEvent.dnsslLifetime)
+
+ testParcel(raEvent, 6)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt b/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt
new file mode 100644
index 0000000..c0cef8f
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import java.lang.reflect.Modifier
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val FIRST_VALIDATION: Int = 1 shl 8
+private const val REVALIDATION: Int = 2 shl 8
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ValidationProbeEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ private infix fun Int.hasType(type: Int) = (type and this) == type
+
+ @Test
+ fun testBuilderAndParcel() {
+ var validationProbeEvent = ValidationProbeEvent.Builder()
+ .setProbeType(ValidationProbeEvent.PROBE_DNS, false).build()
+
+ assertTrue(validationProbeEvent.probeType hasType REVALIDATION)
+
+ validationProbeEvent = ValidationProbeEvent.Builder()
+ .setDurationMs(Long.MAX_VALUE)
+ .setProbeType(ValidationProbeEvent.PROBE_DNS, true)
+ .setReturnCode(ValidationProbeEvent.DNS_SUCCESS)
+ .build()
+
+ assertEquals(Long.MAX_VALUE, validationProbeEvent.durationMs)
+ assertTrue(validationProbeEvent.probeType hasType ValidationProbeEvent.PROBE_DNS)
+ assertTrue(validationProbeEvent.probeType hasType FIRST_VALIDATION)
+ assertEquals(ValidationProbeEvent.DNS_SUCCESS, validationProbeEvent.returnCode)
+
+ testParcel(validationProbeEvent, 3)
+ }
+
+ @Test
+ fun testGetProbeName() {
+ val probeFields = ValidationProbeEvent::class.java.declaredFields.filter {
+ it.type == Int::class.javaPrimitiveType
+ && Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers)
+ && it.name.contains("PROBE")
+ }
+
+ probeFields.forEach {
+ val intValue = it.getInt(null)
+ val stringValue = ValidationProbeEvent.getProbeName(intValue)
+ assertEquals(it.name, stringValue)
+ }
+
+ }
+}
diff --git a/tests/net/java/android/net/IpMemoryStoreTest.java b/tests/net/java/android/net/IpMemoryStoreTest.java
index 18c6768..8ff2de9 100644
--- a/tests/net/java/android/net/IpMemoryStoreTest.java
+++ b/tests/net/java/android/net/IpMemoryStoreTest.java
@@ -16,10 +16,26 @@
package android.net;
-import static org.mockito.ArgumentMatchers.any;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.content.Context;
+import android.net.ipmemorystore.Blob;
+import android.net.ipmemorystore.IOnStatusListener;
+import android.net.ipmemorystore.NetworkAttributes;
+import android.net.ipmemorystore.NetworkAttributesParcelable;
+import android.net.ipmemorystore.Status;
+import android.os.RemoteException;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -27,28 +43,57 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class IpMemoryStoreTest {
+ private static final String TAG = IpMemoryStoreTest.class.getSimpleName();
+ private static final String TEST_CLIENT_ID = "testClientId";
+ private static final String TEST_DATA_NAME = "testData";
+ private static final String TEST_OTHER_DATA_NAME = TEST_DATA_NAME + "Other";
+ private static final byte[] TEST_BLOB_DATA = new byte[] { -3, 6, 8, -9, 12,
+ -128, 0, 89, 112, 91, -34 };
+ private static final NetworkAttributes TEST_NETWORK_ATTRIBUTES = buildTestNetworkAttributes(
+ "hint", 219);
+
@Mock
Context mMockContext;
@Mock
NetworkStackClient mNetworkStackClient;
@Mock
IIpMemoryStore mMockService;
+ @Mock
+ IOnStatusListener mIOnStatusListener;
IpMemoryStore mStore;
+ @Captor
+ ArgumentCaptor<IIpMemoryStoreCallbacks> mCbCaptor;
+ @Captor
+ ArgumentCaptor<NetworkAttributesParcelable> mNapCaptor;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- doAnswer(invocation -> {
- ((IIpMemoryStoreCallbacks) invocation.getArgument(0))
- .onIpMemoryStoreFetched(mMockService);
- return null;
- }).when(mNetworkStackClient).fetchIpMemoryStore(any());
+ }
+
+ private void startIpMemoryStore(boolean supplyService) {
+ if (supplyService) {
+ doAnswer(invocation -> {
+ ((IIpMemoryStoreCallbacks) invocation.getArgument(0))
+ .onIpMemoryStoreFetched(mMockService);
+ return null;
+ }).when(mNetworkStackClient).fetchIpMemoryStore(any());
+ } else {
+ doNothing().when(mNetworkStackClient).fetchIpMemoryStore(mCbCaptor.capture());
+ }
mStore = new IpMemoryStore(mMockContext) {
@Override
protected NetworkStackClient getNetworkStackClient() {
@@ -57,24 +102,228 @@
};
}
- @Test
- public void testNetworkAttributes() {
- // TODO : implement this
+ private static NetworkAttributes buildTestNetworkAttributes(String hint, int mtu) {
+ return new NetworkAttributes.Builder()
+ .setGroupHint(hint)
+ .setMtu(mtu)
+ .build();
}
@Test
- public void testPrivateData() {
- // TODO : implement this
+ public void testNetworkAttributes() throws Exception {
+ startIpMemoryStore(true);
+ final String l2Key = "fakeKey";
+
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ verify(mMockService, times(1)).storeNetworkAttributes(eq(l2Key),
+ mNapCaptor.capture(), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ assertTrue("Retrieve network attributes not successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(TEST_NETWORK_ATTRIBUTES, attr);
+ });
+
+ verify(mMockService, times(1)).retrieveNetworkAttributes(eq(l2Key), any());
}
@Test
- public void testFindL2Key() {
- // TODO : implement this
+ public void testPrivateData() throws RemoteException {
+ startIpMemoryStore(true);
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ verify(mMockService, times(1)).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+ verify(mMockService, times(1)).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
}
@Test
- public void testIsSameNetwork() {
- // TODO : implement this
+ public void testFindL2Key()
+ throws UnknownHostException, RemoteException, Exception {
+ startIpMemoryStore(true);
+ final String l2Key = "fakeKey";
+
+ mStore.findL2Key(TEST_NETWORK_ATTRIBUTES,
+ (status, key) -> {
+ assertTrue("Retrieve network sameness not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ });
+ verify(mMockService, times(1)).findL2Key(mNapCaptor.capture(), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
}
+ @Test
+ public void testIsSameNetwork() throws UnknownHostException, RemoteException {
+ startIpMemoryStore(true);
+ final String l2Key1 = "fakeKey1";
+ final String l2Key2 = "fakeKey2";
+
+ mStore.isSameNetwork(l2Key1, l2Key2,
+ (status, answer) -> {
+ assertFalse("Retrieve network sameness suspiciously successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(Status.ERROR_ILLEGAL_ARGUMENT, status.resultCode);
+ assertNull(answer);
+ });
+ verify(mMockService, times(1)).isSameNetwork(eq(l2Key1), eq(l2Key2), any());
+ }
+
+ @Test
+ public void testEnqueuedIpMsRequests() throws Exception {
+ startIpMemoryStore(false);
+
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ // enqueue multiple ipms requests
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ assertTrue("Retrieve network attributes not successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(TEST_NETWORK_ATTRIBUTES, attr);
+ });
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+
+ // get ipms service ready
+ mCbCaptor.getValue().onIpMemoryStoreFetched(mMockService);
+
+ InOrder inOrder = inOrder(mMockService);
+
+ inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(), any());
+ inOrder.verify(mMockService).retrieveNetworkAttributes(eq(l2Key), any());
+ inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+ inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+ }
+
+ @Test
+ public void testEnqueuedIpMsRequestsWithException() throws Exception {
+ startIpMemoryStore(true);
+ doThrow(RemoteException.class).when(mMockService).retrieveNetworkAttributes(any(), any());
+
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ // enqueue multiple ipms requests
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ assertTrue("Retrieve network attributes not successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(TEST_NETWORK_ATTRIBUTES, attr);
+ });
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+
+ // verify the rest of the queue is still processed in order even if the remote exception
+ // occurs when calling one or more requests
+ InOrder inOrder = inOrder(mMockService);
+
+ inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(), any());
+ inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+ inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+ }
+
+ @Test
+ public void testEnqueuedIpMsRequestsCallbackFunctionWithException() throws Exception {
+ startIpMemoryStore(true);
+
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ // enqueue multiple ipms requests
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ throw new RuntimeException("retrieveNetworkAttributes test");
+ });
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ throw new RuntimeException("storeBlob test");
+ });
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+
+ // verify the rest of the queue is still processed in order even if when one or more
+ // callback throw the remote exception
+ InOrder inOrder = inOrder(mMockService);
+
+ inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(),
+ any());
+ inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+ inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+ }
}
diff --git a/tests/net/java/android/net/util/KeepaliveUtilsTest.kt b/tests/net/java/android/net/util/KeepaliveUtilsTest.kt
new file mode 100644
index 0000000..814e06e
--- /dev/null
+++ b/tests/net/java/android/net/util/KeepaliveUtilsTest.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.util
+
+import android.content.Context
+import android.content.res.Resources
+import android.net.NetworkCapabilities
+import android.net.NetworkCapabilities.MAX_TRANSPORT
+import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
+import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
+import android.net.NetworkCapabilities.TRANSPORT_VPN
+import android.net.NetworkCapabilities.TRANSPORT_WIFI
+import androidx.test.filters.SmallTest
+import com.android.internal.R
+import org.junit.Assert.assertArrayEquals
+import org.junit.Assert.assertEquals
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+
+/**
+ * Tests for [KeepaliveUtils].
+ *
+ * Build, install and run with:
+ * atest android.net.util.KeepaliveUtilsTest
+ */
+@RunWith(JUnit4::class)
+@SmallTest
+class KeepaliveUtilsTest {
+
+ // Prepare mocked context with given resource strings.
+ private fun getMockedContextWithStringArrayRes(id: Int, res: Array<out String?>?): Context {
+ val mockRes = mock(Resources::class.java)
+ doReturn(res).`when`(mockRes).getStringArray(ArgumentMatchers.eq(id))
+
+ return mock(Context::class.java).apply {
+ doReturn(mockRes).`when`(this).getResources()
+ }
+ }
+
+ @Test
+ fun testGetSupportedKeepalives() {
+ fun assertRunWithException(res: Array<out String?>?) {
+ try {
+ val mockContext = getMockedContextWithStringArrayRes(
+ R.array.config_networkSupportedKeepaliveCount, res)
+ KeepaliveUtils.getSupportedKeepalives(mockContext)
+ fail("Expected KeepaliveDeviceConfigurationException")
+ } catch (expected: KeepaliveUtils.KeepaliveDeviceConfigurationException) {
+ }
+ }
+
+ // Check resource with various invalid format.
+ assertRunWithException(null)
+ assertRunWithException(arrayOf<String?>(null))
+ assertRunWithException(arrayOfNulls<String?>(10))
+ assertRunWithException(arrayOf(""))
+ assertRunWithException(arrayOf("3,ABC"))
+ assertRunWithException(arrayOf("6,3,3"))
+ assertRunWithException(arrayOf("5"))
+
+ // Check resource with invalid slots value.
+ assertRunWithException(arrayOf("2,2"))
+ assertRunWithException(arrayOf("3,-1"))
+
+ // Check resource with invalid transport type.
+ assertRunWithException(arrayOf("-1,3"))
+ assertRunWithException(arrayOf("10,3"))
+
+ // Check valid customization generates expected array.
+ val validRes = arrayOf("0,3", "1,0", "4,4")
+ val expectedValidRes = intArrayOf(3, 0, 0, 0, 4, 0, 0, 0)
+
+ val mockContext = getMockedContextWithStringArrayRes(
+ R.array.config_networkSupportedKeepaliveCount, validRes)
+ val actual = KeepaliveUtils.getSupportedKeepalives(mockContext)
+ assertArrayEquals(expectedValidRes, actual)
+ }
+
+ @Test
+ fun testGetSupportedKeepalivesForNetworkCapabilities() {
+ // Mock customized supported keepalives for each transport type, and assuming:
+ // 3 for cellular,
+ // 6 for wifi,
+ // 0 for others.
+ val cust = IntArray(MAX_TRANSPORT + 1).apply {
+ this[TRANSPORT_CELLULAR] = 3
+ this[TRANSPORT_WIFI] = 6
+ }
+
+ val nc = NetworkCapabilities()
+ // Check supported keepalives with single transport type.
+ nc.transportTypes = intArrayOf(TRANSPORT_CELLULAR)
+ assertEquals(3, KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(cust, nc))
+
+ // Check supported keepalives with multiple transport types.
+ nc.transportTypes = intArrayOf(TRANSPORT_WIFI, TRANSPORT_VPN)
+ assertEquals(0, KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(cust, nc))
+
+ // Check supported keepalives with non-customized transport type.
+ nc.transportTypes = intArrayOf(TRANSPORT_ETHERNET)
+ assertEquals(0, KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(cust, nc))
+
+ // Check supported keepalives with undefined transport type.
+ nc.transportTypes = intArrayOf(MAX_TRANSPORT + 1)
+ try {
+ KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(cust, nc)
+ fail("Expected ArrayIndexOutOfBoundsException")
+ } catch (expected: ArrayIndexOutOfBoundsException) {
+ }
+ }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 363ac9c..b0cc207 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -28,6 +28,7 @@
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
import static android.net.ConnectivityManager.TYPE_NONE;
+import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
@@ -489,7 +490,7 @@
MockNetworkAgent(int transport, LinkProperties linkProperties) {
final int type = transportToLegacyType(transport);
- final String typeName = ConnectivityManager.getNetworkTypeName(transport);
+ final String typeName = ConnectivityManager.getNetworkTypeName(type);
mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addTransportType(transport);
@@ -619,6 +620,10 @@
mNetworkAgent.sendNetworkScore(mScore);
}
+ public int getScore() {
+ return mScore;
+ }
+
public void explicitlySelected(boolean acceptUnvalidated) {
mNetworkAgent.explicitlySelected(acceptUnvalidated);
}
@@ -1330,6 +1335,8 @@
return TYPE_WIFI;
case TRANSPORT_CELLULAR:
return TYPE_MOBILE;
+ case TRANSPORT_VPN:
+ return TYPE_VPN;
default:
return TYPE_NONE;
}
@@ -3854,6 +3861,9 @@
networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
testFactory.waitForRequests();
+ // unregister network callback - a no-op, but should not fail
+ mCm.unregisterNetworkCallback(networkCallback);
+
testFactory.unregister();
handlerThread.quit();
}
@@ -4332,8 +4342,9 @@
}
// Check that there is no port leaked after all keepalives and sockets are closed.
- assertFalse(isUdpPortInUse(srcPort));
- assertFalse(isUdpPortInUse(srcPort2));
+ // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
+ // assertFalse(isUdpPortInUse(srcPort));
+ // assertFalse(isUdpPortInUse(srcPort2));
mWiFiNetworkAgent.disconnect();
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
@@ -4461,7 +4472,8 @@
assertEquals(anyIPv4, sa.getAddress());
testPfd.close();
- assertFalse(isUdpPortInUse(srcPort));
+ // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
+ // assertFalse(isUdpPortInUse(srcPort));
mWiFiNetworkAgent.disconnect();
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
@@ -5365,6 +5377,58 @@
}
@Test
+ public void testVpnUnvalidated() throws Exception {
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(callback);
+
+ // Bring up Ethernet.
+ mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
+ mEthernetNetworkAgent.connect(true);
+ callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
+ callback.assertNoCallback();
+
+ // Bring up a VPN that has the INTERNET capability, initially unvalidated.
+ final int uid = Process.myUid();
+ final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ final ArraySet<UidRange> ranges = new ArraySet<>();
+ ranges.add(new UidRange(uid, uid));
+ mMockVpn.setNetworkAgent(vpnNetworkAgent);
+ mMockVpn.setUids(ranges);
+ vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
+ mMockVpn.connect();
+
+ // Even though the VPN is unvalidated, it becomes the default network for our app.
+ callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
+ // TODO: this looks like a spurious callback.
+ callback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
+ callback.assertNoCallback();
+
+ assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
+ assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
+ assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+ NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
+ assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
+ assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
+
+ assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
+ assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
+ vpnNetworkAgent.mNetworkCapabilities));
+
+ // Pretend that the VPN network validates.
+ vpnNetworkAgent.setNetworkValid();
+ vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+ // Expect to see the validated capability, but no other changes, because the VPN is already
+ // the default network for the app.
+ callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
+ callback.assertNoCallback();
+
+ vpnNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
+ }
+
+ @Test
public void testVpnSetUnderlyingNetworks() {
final int uid = Process.myUid();
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 7c40adf..71b72b8 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -32,6 +32,7 @@
import android.app.AppOpsManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.net.INetd;
import android.net.IpSecAlgorithm;
import android.net.IpSecConfig;
@@ -57,6 +58,7 @@
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import java.net.Inet4Address;
import java.net.Socket;
import java.util.Arrays;
import java.util.Collection;
@@ -119,6 +121,11 @@
}
@Override
+ public PackageManager getPackageManager() {
+ return mMockPkgMgr;
+ }
+
+ @Override
public void enforceCallingOrSelfPermission(String permission, String message) {
if (permission == android.Manifest.permission.MANAGE_IPSEC_TUNNELS) {
return;
@@ -128,6 +135,7 @@
};
INetd mMockNetd;
+ PackageManager mMockPkgMgr;
IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
IpSecService mIpSecService;
Network fakeNetwork = new Network(0xAB);
@@ -152,11 +160,16 @@
@Before
public void setUp() throws Exception {
mMockNetd = mock(INetd.class);
+ mMockPkgMgr = mock(PackageManager.class);
mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
// Injecting mock netd
when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
+
+ // PackageManager should always return true (feature flag tests in IpSecServiceTest)
+ when(mMockPkgMgr.hasSystemFeature(anyString())).thenReturn(true);
+
// A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED.
when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("blessedPackage")))
.thenReturn(AppOpsManager.MODE_ALLOWED);
@@ -709,4 +722,18 @@
} catch (SecurityException expected) {
}
}
+
+ @Test
+ public void testFeatureFlagVerification() throws Exception {
+ when(mMockPkgMgr.hasSystemFeature(eq(PackageManager.FEATURE_IPSEC_TUNNELS)))
+ .thenReturn(false);
+
+ try {
+ String addr = Inet4Address.getLoopbackAddress().getHostAddress();
+ mIpSecService.createTunnelInterface(
+ addr, addr, new Network(0), new Binder(), "blessedPackage");
+ fail("Expected UnsupportedOperationException for disabled feature");
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
}
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index d5b2c87..3a07166 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -21,11 +21,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -59,16 +56,11 @@
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 java.io.PrintWriter;
import java.io.StringWriter;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -98,48 +90,6 @@
}
@Test
- public void testLoggingEvents() throws Exception {
- IpConnectivityLog logger = new IpConnectivityLog(mMockService);
-
- assertTrue(logger.log(1, FAKE_EV));
- assertTrue(logger.log(2, FAKE_EV));
- assertTrue(logger.log(3, FAKE_EV));
-
- List<ConnectivityMetricsEvent> got = verifyEvents(3);
- assertEventsEqual(expectedEvent(1), got.get(0));
- assertEventsEqual(expectedEvent(2), got.get(1));
- assertEventsEqual(expectedEvent(3), got.get(2));
- }
-
- @Test
- public void testLoggingEventsWithMultipleCallers() throws Exception {
- IpConnectivityLog logger = new IpConnectivityLog(mMockService);
-
- final int nCallers = 10;
- final int nEvents = 10;
- for (int n = 0; n < nCallers; n++) {
- final int i = n;
- new Thread() {
- public void run() {
- for (int j = 0; j < nEvents; j++) {
- assertTrue(logger.log(1 + i * 100 + j, FAKE_EV));
- }
- }
- }.start();
- }
-
- List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
- Collections.sort(got, EVENT_COMPARATOR);
- Iterator<ConnectivityMetricsEvent> iter = got.iterator();
- for (int i = 0; i < nCallers; i++) {
- for (int j = 0; j < nEvents; j++) {
- int expectedTimestamp = 1 + i * 100 + j;
- assertEventsEqual(expectedEvent(expectedTimestamp), iter.next());
- }
- }
- }
-
- @Test
public void testBufferFlushing() {
String output1 = getdump("flush");
assertEquals("", output1);
@@ -653,16 +603,7 @@
return nai;
}
- List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
- ArgumentCaptor<ConnectivityMetricsEvent> captor =
- ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
- verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
- return captor.getAllValues();
- }
- List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
- return verifyEvents(n, 10);
- }
static void verifySerialization(String want, String output) {
try {
@@ -674,28 +615,4 @@
fail(e.toString());
}
}
-
- static String joinLines(String ... elems) {
- StringBuilder b = new StringBuilder();
- for (String s : elems) {
- b.append(s).append("\n");
- }
- return b.toString();
- }
-
- static ConnectivityMetricsEvent expectedEvent(int timestamp) {
- ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
- ev.timestamp = timestamp;
- ev.data = FAKE_EV;
- return ev;
- }
-
- /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
- static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
- assertEquals(expected.timestamp, got.timestamp);
- assertEquals(expected.data, got.data);
- }
-
- static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
- Comparator.comparingLong((ev) -> ev.timestamp);
}
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
index a83faf3..fb84611 100644
--- a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
+++ b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.connectivity.ipmemorystore;
+package com.android.server.net.ipmemorystore;
import static org.junit.Assert.assertEquals;
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 326c88d..53372bf 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -41,6 +41,7 @@
windows: {
enabled: true,
cflags: ["-Wno-maybe-uninitialized"],
+ ldflags: ["-static"],
},
darwin: {
cflags: ["-D_DARWIN_UNLIMITED_STREAMS"],
diff --git a/tools/aapt2/ResourceValues_test.cpp b/tools/aapt2/ResourceValues_test.cpp
index c4a1108..dbf5114 100644
--- a/tools/aapt2/ResourceValues_test.cpp
+++ b/tools/aapt2/ResourceValues_test.cpp
@@ -284,8 +284,58 @@
EXPECT_FALSE(attr_three.IsCompatibleWith(attr_one));
EXPECT_FALSE(attr_three.IsCompatibleWith(attr_two));
- EXPECT_FALSE(attr_three.IsCompatibleWith(attr_three));
+ EXPECT_TRUE(attr_three.IsCompatibleWith(attr_three));
EXPECT_FALSE(attr_three.IsCompatibleWith(attr_four));
+
+ EXPECT_FALSE(attr_four.IsCompatibleWith(attr_one));
+ EXPECT_FALSE(attr_four.IsCompatibleWith(attr_two));
+ EXPECT_FALSE(attr_four.IsCompatibleWith(attr_three));
+ EXPECT_TRUE(attr_four.IsCompatibleWith(attr_four));
+}
+
+TEST(ResourcesValuesTest, AttributeEnumIsCompatible) {
+ Attribute attr_one(TYPE_ENUM);
+ attr_one.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/foo")), 0x01u});
+ attr_one.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/bar")), 0x07u});
+
+ Attribute attr_two(TYPE_ENUM);
+ attr_two.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/foo")), 0x01u});
+ attr_two.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/bar")), 0x07u});
+ EXPECT_TRUE(attr_one.IsCompatibleWith(attr_two));
+}
+
+TEST(ResourcesValuesTest, DifferentAttributeEnumDifferentNameIsNotCompatible) {
+ Attribute attr_one(TYPE_ENUM);
+ attr_one.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/foo")), 0x01u});
+ attr_one.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/bar")), 0x07u});
+
+ Attribute attr_two(TYPE_ENUM);
+ attr_two.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/foo")), 0x01u});
+ attr_one.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/baz")), 0x07u});
+ EXPECT_FALSE(attr_one.IsCompatibleWith(attr_two));
+}
+
+TEST(ResourcesValuesTest, DifferentAttributeEnumDifferentValueIsNotCompatible) {
+ Attribute attr_one(TYPE_ENUM);
+ attr_one.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/foo")), 0x01u});
+ attr_one.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/bar")), 0x07u});
+
+ Attribute attr_two(TYPE_ENUM);
+ attr_two.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/foo")), 0x01u});
+ attr_two.symbols.push_back(
+ Attribute::Symbol{Reference(test::ParseNameOrDie("android:id/bar")), 0x09u});
+ EXPECT_FALSE(attr_one.IsCompatibleWith(attr_two));
}
} // namespace aapt
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index be9c84b..78d42a1 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -408,54 +408,6 @@
ASSERT_FALSE(merger.Merge({}, overlay.get(), true /*overlay*/));
}
-TEST_F(TableMergerTest, FailToOverrideConflictingFlagsAndEnumsWithOverlay) {
- std::unique_ptr<ResourceTable> base =
- test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
- .AddValue("attr/foo", test::AttributeBuilder()
- .SetTypeMask(android::ResTable_map::TYPE_FLAGS)
- .Build())
- .Build();
-
- std::unique_ptr<ResourceTable> overlay =
- test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
- .AddValue("attr/foo", test::AttributeBuilder()
- .SetTypeMask(android::ResTable_map::TYPE_FLAGS)
- .SetWeak(false)
- .Build())
- .Build();
-
- ResourceTable final_table;
- TableMergerOptions options;
- options.auto_add_overlay = false;
- TableMerger merger(context_.get(), &final_table, options);
-
- ASSERT_TRUE(merger.Merge({}, base.get(), false /*overlay*/));
- ASSERT_FALSE(merger.Merge({}, overlay.get(), true /*overlay*/));
-
- base = test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
- .AddValue("attr/foo", test::AttributeBuilder()
- .SetTypeMask(android::ResTable_map::TYPE_ENUM)
- .Build())
- .Build();
-
- overlay = test::ResourceTableBuilder()
- .SetPackageId("", 0x7f)
- .AddValue("attr/foo", test::AttributeBuilder()
- .SetTypeMask(android::ResTable_map::TYPE_ENUM)
- .SetWeak(false)
- .Build())
- .Build();
-
- ResourceTable final_table2;
- TableMerger merger2(context_.get(), &final_table2, options);
-
- ASSERT_TRUE(merger2.Merge({}, base.get(), false /*overlay*/));
- ASSERT_FALSE(merger2.Merge({}, overlay.get(), true /*overlay*/));
-}
-
TEST_F(TableMergerTest, FailToMergeNewResourceWithoutAutoAddOverlay) {
std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder().SetPackageId("", 0x7f).Build();
diff --git a/tools/apilint/apilint b/tools/apilint/apilint
new file mode 100755
index 0000000..e42857f
--- /dev/null
+++ b/tools/apilint/apilint
@@ -0,0 +1,147 @@
+#!/bin/bash
+
+# Copyright (C) 2019 The Android Open 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.
+
+if [ "$1" == "--help" -o "$1" == "-h" ]; then
+echo "Usage: apilint [FILTERS...]"
+echo " Shows lint from currently open files (as diffed from HEAD), i.e. errors"
+echo " you will receive if you upload this CL."
+echo
+echo "Usage: apilint --all [FILTERS...]"
+echo " Shows all lint errors present in the current working directory, regardless"
+echo " of when they were added."
+echo
+echo "Usage: apilint --level API_LEVEL [FILTERS...]"
+echo " Shows lint as it stands in API_LEVEL"
+echo
+echo "Usage: apilint --shal SHA [FILTERS...]"
+echo " Shows lint from locally commited git change SHA."
+echo
+echo "Usage: apilint --unreleased [FILTERS...]"
+echo " Shows all lint errors in the current working directory directory added since"
+echo " the last released SDK version."
+echo
+echo "FILTERS"
+echo " List of class or package names by which to filter the results."
+echo
+exit
+fi
+
+if [ \( -z "$ANDROID_BUILD_TOP" \) \
+ -a \( ! -f frameworks/base/api/current.txt \) \
+ -a \( ! -f frameworks/base/api/system-current.txt \) \
+ ]; then
+ echo "apilint must be run either with ANDROID_BUILD_TOP set or from the" 1>&2
+ echo "root of the android source tree" 1>&2
+ exit 1
+fi
+
+if [ ${ANDROID_BUILD_TOP:0:1} != "/" ]; then
+ echo "ANDROID_BUILD_TOP must be an absolute path, not: $ANDROID_BUILD_TOP" 1>&2
+ exit 1
+fi
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+ ANDROID_BUILD_TOP=$(pwd)
+fi
+
+FW_BASE=$ANDROID_BUILD_TOP/frameworks/base
+
+MODE=open
+
+OPTIONS=$(getopt -n apilint -o "" -l "all,sha:,unreleased" -- "$@")
+
+[ $? -eq 0 ] || {
+ exit 1
+}
+
+eval set -- "$OPTIONS"
+while true; do
+ case "$1" in
+ --all)
+ MODE=all
+ ;;
+ --sha)
+ shift; # The arg is next in position args
+ MODE=sha
+ SHA=$1
+ ;;
+ --unreleased)
+ MODE=unreleased
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+ shift
+done
+FILTERS=
+for var in "$@"
+do
+ FILTERS="$FILTERS --filter $var"
+done
+
+if [ $MODE = "all" ]; then
+ python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
+ --title "SDK" \
+ $FILTERS \
+ $ANDROID_BUILD_TOP/frameworks/base/api/current.txt
+ python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
+ --title "SystemApi" \
+ $FILTERS \
+ --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
+ $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt
+elif [ $MODE = "open" ]; then
+ python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
+ --title "SDK" \
+ $FILTERS \
+ $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
+ <(cd $FW_BASE ; git show HEAD:api/current.txt)
+ python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
+ --title "SystemApi" \
+ $FILTERS \
+ --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
+ --base-previous <(cd $FW_BASE ; git show HEAD:api/current.txt) \
+ $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt \
+ <(cd $FW_BASE ; git show HEAD:api/system-current.txt)
+elif [ $MODE = "sha" ]; then
+ python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
+ --title "SDK" \
+ $FILTERS \
+ <(cd $FW_BASE ; git show $SHA:api/current.txt) \
+ <(cd $FW_BASE ; git show $SHA^:api/current.txt)
+ python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
+ --title "SystemApi" \
+ $FILTERS \
+ --base-current <(cd $FW_BASE ; git show $SHA:api/current.txt) \
+ --base-previous <(cd $FW_BASE ; git show $SHA^:api/current.txt) \
+ <(cd $FW_BASE ; git show $SHA:api/system-current.txt) \
+ <(cd $FW_BASE ; git show $SHA^:api/system-current.txt)
+elif [ $MODE = "unreleased" ]; then
+ LAST_SDK=$(ls $ANDROID_BUILD_TOP/prebuilts/sdk | grep "^[0-9][0-9]*$" | sort -n | tail -n 1)
+ python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
+ --title "SDK" \
+ $FILTERS \
+ $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
+ $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/public/api/android.txt
+ python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
+ --title "SystemApi" \
+ $FILTERS \
+ --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
+ --base-previous $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/public/api/android.txt \
+ $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt \
+ $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/system/api/android.txt
+fi
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index f41426d..9e42c04 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -707,6 +707,7 @@
class Failure():
def __init__(self, sig, clazz, detail, error, rule, msg):
+ self.clazz = clazz
self.sig = sig
self.error = error
self.rule = rule
@@ -2126,6 +2127,15 @@
return failures
+def match_filter(filters, fullname):
+ for f in filters:
+ if fullname == f:
+ return True
+ if fullname.startswith(f + '.'):
+ return True
+ return False
+
+
def show_deprecations_at_birth(cur, prev):
"""Show API deprecations at birth."""
global failures
@@ -2199,12 +2209,9 @@
print " ", "".join([ str(stats[k]).ljust(20) for k in sorted(stats.keys()) ])
-if __name__ == "__main__":
+def main():
parser = argparse.ArgumentParser(description="Enforces common Android public API design \
patterns. It ignores lint messages from a previous API level, if provided.")
- parser.add_argument("current.txt", type=argparse.FileType('r'), help="current.txt")
- parser.add_argument("previous.txt", nargs='?', type=argparse.FileType('r'), default=None,
- help="previous.txt")
parser.add_argument("--base-current", nargs='?', type=argparse.FileType('r'), default=None,
help="The base current.txt to use when examining system-current.txt or"
" test-current.txt")
@@ -2213,6 +2220,8 @@
" test-previous.txt")
parser.add_argument("--no-color", action='store_const', const=True,
help="Disable terminal colors")
+ parser.add_argument("--color", action='store_const', const=True,
+ help="Use terminal colors")
parser.add_argument("--allow-google", action='store_const', const=True,
help="Allow references to Google")
parser.add_argument("--show-noticed", action='store_const', const=True,
@@ -2221,10 +2230,21 @@
help="Show API deprecations at birth")
parser.add_argument("--show-stats", action='store_const', const=True,
help="Show API stats")
+ parser.add_argument("--title", action='store', default=None,
+ help="Title to put in for display purposes")
+ parser.add_argument("--filter", action="append",
+ help="If provided, only show lint for the given packages or classes.")
+ parser.add_argument("current.txt", type=argparse.FileType('r'), help="current.txt")
+ parser.add_argument("previous.txt", nargs='?', type=argparse.FileType('r'), default=None,
+ help="previous.txt")
args = vars(parser.parse_args())
if args['no_color']:
USE_COLOR = False
+ elif args['color']:
+ USE_COLOR = True
+ else:
+ USE_COLOR = sys.stdout.isatty()
if args['allow_google']:
ALLOW_GOOGLE = True
@@ -2233,6 +2253,12 @@
base_current_file = args['base_current']
previous_file = args['previous.txt']
base_previous_file = args['base_previous']
+ filters = args['filter']
+ if not filters:
+ filters = []
+ title = args['title']
+ if not title:
+ title = current_file.name
if args['show_deprecations_at_birth']:
with current_file as f:
@@ -2290,6 +2316,11 @@
print
"""
+ # ignore everything but the given filters, if provided
+ if filters:
+ cur_fail = dict([(key, failure) for key, failure in cur_fail.iteritems()
+ if match_filter(filters, failure.clazz.fullname)])
+
if args['show_noticed'] and len(cur_noticed) != 0:
print "%s API changes noticed %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
for f in sorted(cur_noticed.keys()):
@@ -2297,8 +2328,20 @@
print
if len(cur_fail) != 0:
- print "%s API style issues %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
+ print "%s API style issues: %s %s" % ((format(fg=WHITE, bg=BLUE, bold=True),
+ title, format(reset=True)))
+ for f in filters:
+ print "%s filter: %s %s" % ((format(fg=WHITE, bg=BLUE, bold=True),
+ f, format(reset=True)))
+ print
for f in sorted(cur_fail):
print cur_fail[f]
print
+ print "%d errors" % len(cur_fail)
sys.exit(77)
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ sys.exit(1)
diff --git a/tools/apilint/apilint_test.py b/tools/apilint/apilint_test.py
index 5cb43db..811cb9a 100644
--- a/tools/apilint/apilint_test.py
+++ b/tools/apilint/apilint_test.py
@@ -392,5 +392,23 @@
p = self._package("package @Rt(a.b.L_G_P) @RestrictTo(a.b.C) an.pref.int {")
self.assertEquals('an.pref.int', p.name)
+class FilterTests(unittest.TestCase):
+ def test_filter_match_prefix(self):
+ self.assertTrue(apilint.match_filter(["a"], "a.B"))
+ self.assertTrue(apilint.match_filter(["a.B"], "a.B.C"))
+
+ def test_filter_dont_match_prefix(self):
+ self.assertFalse(apilint.match_filter(["c"], "a.B"))
+ self.assertFalse(apilint.match_filter(["a."], "a.B"))
+ self.assertFalse(apilint.match_filter(["a.B."], "a.B.C"))
+
+ def test_filter_match_exact(self):
+ self.assertTrue(apilint.match_filter(["a.B"], "a.B"))
+
+ def test_filter_dont_match_exact(self):
+ self.assertFalse(apilint.match_filter([""], "a.B"))
+ self.assertFalse(apilint.match_filter(["a.C"], "a.B"))
+ self.assertFalse(apilint.match_filter(["a.C"], "a.B"))
+
if __name__ == "__main__":
unittest.main()
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 21fe22e..c0c0361 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -155,6 +155,16 @@
public static final int KEY_MGMT_EAP_SUITE_B_192 = 10;
/**
* @hide
+ * Security key management scheme: FT_SAE.
+ */
+ public static final int KEY_MGMT_FT_SAE = 11;
+ /**
+ * @hide
+ * Security key management scheme: OWE in transition mode.
+ */
+ public static final int KEY_MGMT_OWE_TRANSITION = 12;
+ /**
+ * @hide
* No cipher suite.
*/
public static final int CIPHER_NONE = 0;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index be227e7..ed41642 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1906,7 +1906,8 @@
if (this.meteredOverride != METERED_OVERRIDE_NONE) {
sbuf.append(" meteredOverride ").append(meteredOverride).append("\n");
}
- sbuf.append(" macRandomizationSetting ").append(macRandomizationSetting).append("\n");
+ sbuf.append(" macRandomizationSetting: ").append(macRandomizationSetting).append("\n");
+ sbuf.append(" mRandomizedMacAddress: ").append(mRandomizedMacAddress).append("\n");
sbuf.append(" KeyMgmt:");
for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
if (this.allowedKeyManagement.get(k)) {
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index a779378..cd659e2 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -93,7 +93,9 @@
* {@link WifiP2pInfo} contains the address of the group owner
* {@link WifiP2pInfo#groupOwnerAddress} and a flag {@link WifiP2pInfo#isGroupOwner} to indicate
* if the current device is a p2p group owner. A p2p client can thus communicate with
- * the p2p group owner through a socket connection.
+ * the p2p group owner through a socket connection. If the current device is the p2p group owner,
+ * {@link WifiP2pInfo#groupOwnerAddress} is anonymized unless the caller holds the
+ * {@code android.Manifest.permission#LOCAL_MAC_ADDRESS} permission.
*
* <p> With peer discovery using {@link #discoverPeers}, an application discovers the neighboring
* peers, but has no good way to figure out which peer to establish a connection with. For example,
@@ -300,6 +302,11 @@
* To get information notifications on P2P getting enabled refers
* {@link #WIFI_P2P_STATE_ENABLED}.
*
+ * <p> The {@link #EXTRA_WIFI_P2P_DEVICE} extra contains an anonymized version of the device's
+ * MAC address. Callers holding the {@code android.Manifest.permission#LOCAL_MAC_ADDRESS}
+ * permission can use {@link #requestDeviceInfo} to obtain the actual MAC address of this
+ * device.
+ *
* All of these permissions are required to receive this broadcast:
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and
* {@link android.Manifest.permission#ACCESS_WIFI_STATE}
@@ -1881,6 +1888,10 @@
* <p> This {@link android.net.wifi.p2p.WifiP2pDevice} is returned using the
* {@link DeviceInfoListener} listener.
*
+ * <p> {@link android.net.wifi.p2p.WifiP2pDevice#deviceAddress} is only available if the caller
+ * holds the {@code android.Manifest.permission#LOCAL_MAC_ADDRESS} permission, and holds the
+ * anonymized MAC address (02:00:00:00:00:00) otherwise.
+ *
* <p> This information is also included in the {@link #WIFI_P2P_THIS_DEVICE_CHANGED_ACTION}
* broadcast event with extra {@link #EXTRA_WIFI_P2P_DEVICE}.
*